Add EntityFramework Core IQueryable support to GraphQL
See Milestones for release notes.
https://nuget.org/packages/GraphQL.EntityFramework/
Memory designed by H Alberto Gongora from The Noun Project
Adds EntityFramework Core IQueryable support to GraphQL
License: MIT License
Add EntityFramework Core IQueryable support to GraphQL
See Milestones for release notes.
https://nuget.org/packages/GraphQL.EntityFramework/
Memory designed by H Alberto Gongora from The Noun Project
The phrase "No null checking of nested values is done" is present in the readme, when describing "where" queries. It is not obvious what this means.
I can think of multiple interpretations:
Possibly there are even more interpretations. Please clarify what the actual behavior is.
Hi Simon,
thanks for all the help.
1 question: Do you see any disadvantages compared to Odata when using graphQL with your library?
this is a cheat sheet showing the OData features.
Maybe only count would be missing here..
Suggestion: Although QueryGraphType.AddQueryField has an arguments parameter, AddSingleField does not. I would like to suggest that this feature be added. This will be useful because I want to implement the mutation class as a QueryGraphType, utilizing AddSingleField to allow the return type to provide potentially the entire graph (including subtables) of the updated data. So it would be coded like any other mutation, except the last line would be return dbContext.MyTable.Where(x => x.Id == argumentModel.Id). This would have another benefit of not having to provide separate return graphs/models for mutations, as they can simply return the same graph/model as the query. Of course, another call to the database would be made for every update, but this could be viewed as a benefit, and would be necessary anyway if subtables were requested.
As the title says, I'd like to be able to pass an ISNULL through to SQL. In normal EF I'd probably do something like .Where(i => i.Property1 ?? i.Property2)
, I don't see a way to put the null coalescing operator into a GQL query.
Hi, In the documentation is written
There is a helper methods to perform the above:
EfGraphQLConventions.RegisterConnectionTypesInContainer(IServiceCollection services);
https://github.com/SimonCropp/GraphQL.EntityFramework/blob/master/pages/configuration.md
But there is not such a helper
Could you please add this helper? Or can you point me, how to register that as action? thx
Hi Simon,
I want to add sql logging to log sqlCommands executed.
You use
var myDataContext = InMemoryContextBuilder.Build<MyDataContext>();
in my other project i have this
services.AddDbContext<DbContextOrderStatuses>(options => options.UseLoggerFactory(factory).UseSqlServer(orderStatusConnString));
how can i access the DbContextOptionsBuilders ? Or should i dump InMemoryContextBuilder and use my own?
thanks
I'm currently evaluating moving from an OData backend to GraphQL and was trying to find the best approach to retrieve aggregated values from a GraphQL endpoint. I've been looking at your project and it looks to solve a most of the non-aggregated data access I need (thank you), but I wasn't sure if retrieving aggregated values was within the scope of the project or the best approach to take.
In general, I've seen retrieving aggregated values within GraphQL is outside the scope of the GraphQL spec directly, but have seen some support and proposals to enable something like:
query PostData {
viewer {
allArticles(where:{ createdAt: { gt: "2016", lt: "2017" }}) {
aggregations {
count
sum {
recommends
reads
}
avg {
recommends
reads
}
}
}
}
}
Moving from OData, this is directly supported using $apply
transforms, and I've written an object-based query syntax for it that might also be used for inspiration.
My questions / proposal are:
GraphQL.EntityFramework
to expose aggregated values (customize the resolve
query in a AddQueryField
for example)?aggregations
in a standard way be considered for this project (via a syntax similar to that above)?According to the documentation "Currently the only supported identity member (property or field) name is Id."
Just in case, are [Key] annotations supported for specifying the entity key property? If not, any hints on what would be required to change?
Thanks.
I was evaluating this project for an upcoming project and found some places where suboptimal database access was being made.
Consider a simple setup where (omitting a lot of boilerplate code):
public class MyContext : DbContext
{
public DbSet<MyItem> Items { get; set; }
}
public class MyItem
{
public int Id { get; set; }
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
}
public class MyQuery : EfObjectGraphType
{
public MyQuery(IEfGraphQLService gql, MyContext db)
: base(gql)
{
AddQueryConnectionField(
name: "allItems",
resolve: context => db.Items);
}
}
Performing a simple GraphQL query:
{
allItems { totalCount }
}
Will cause the following database queries to be made by EF Core:
SELECT COUNT(*)
FROM "Items" AS "i"
SELECT "i"."Id", "i"."A", "i"."B", "i"."C"
FROM "Items" AS "i"
LIMIT @__p_1 OFFSET @__p_0
From what I gathered from looking at the source, this is because when resolving the Connection<MyItem>
there is no optimization being made to not query the list of items when neither edges { node }
nor items
is selected. I would expect only the following database query to be made:
SELECT COUNT(*)
FROM "Items" AS "i"
In the same vein the following query will needlessly retrieve the total count (with a SELECT COUNT(*)...
database query):
{
allItems { items { id } }
}
In fact, for the aforementioned query, I would expect the only following database query to be made by EF Core:
SELECT "i"."Id"
FROM "Items" AS "i"
LIMIT @__p_1 OFFSET @__p_0
Unfortunately, however, when resolving the Connection<MyItem>
the entire entity is being loaded (with tracking, .AsNoTracking()
can be specified manually in the EfObjectGraphType
implementation on the AddQueryConnectionField
call but I imagine it is a sane default to have) instead of just the required properties. This can be achieved in EF Core with something like following, where the result will only contain the Id
property set and have leave the other properties unset:
using (var context = new MyContext())
{
var result = await db.Items
.Select(i => new MyItem
{
Id = i.Id
})
.ToListAsync();
}
The above code would result in the following database query being generated by EF Core:
SELECT "i"."Id"
FROM "Items" AS "i"
Furthermore, this can be done programmatically with Expression
with something like the following example being as far as I can tell exactly equivalent to the previous operation:
using (var context = new MyContext())
{
var itemParameter = Expression.Parameter(typeof(MyItem), "i");
var idProperty = typeof(MyItem).GetProperty("Id");
var expression = Expression.Lambda<Func<MyItem, MyItem>>(
Expression.MemberInit(
Expression.New(typeof(MyItem)),
Expression.Bind(
idProperty,
Expression.MakeMemberAccess(itemParameter, idProperty))),
itemParameter);
var result = await context.Items
.Select(expression)
.ToListAsync();
}
I have not tested this with navigation collection connections so I do not know whether it has the same issues but from quickly glancing at the code it seems to.
I did some quick and dirty benchmarking using an SQLite database (disclamer these are probably not valid or accurate benchmarks and are just for illustrative purposes - code provided in this gist). Using expressions to read only the Id
property from the database is roughly 270% faster than retrieving an entire entity with tracking (what is currently being done) but only 40% faster than retrieving an entire entity without tracking (this should definitely be suggested in the documentation). However, retrieving the entire entity using expressions (so an Expression.Bind
per property) is roughly 15% slower than just retrieving the entire entity untracked.
This feature would probably require quite a lot of work and is something I would not be able to commit to. I decided to just post my findings here in case someone else was interested in optimizing implementing these features or funding their development.
Is there any way to add query field and resolve the context without relying on a generic implementation.
I need to call AddQueryField
and resolve the data context using non generic class DbContext
which return non generic DbSet
.
I have read the file EfGraphQLService_Queryable.cs and all AddQueryField
overloads should at least specify the return type at compile time.
This doesn't support fragments, it seems. Would it be a hard feature to add?
Hi, I have been checking out this library and I have it working on a test project for non-connection queries.
I am getting an error using AddNavigationConnectionField()
when trying to get a list of paged orders for a customer.
"GraphQL.ExecutionError: Error trying to resolve customers. ---> System.Collections.Generic.KeyNotFoundException: The given key 'System.Object' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at IncludeAppender.AddField(List`1 list, Field field, String parentPath, FieldType fieldType, List`1 parentNavigationProperties) in src\GraphQL.EntityFramework\IncludeAppender.cs:line 76
at IncludeAppender.ProcessSubFields(List`1 list, String parentPath, ICollection`1 subFields, IComplexGraphType complexGraph, List`1 navigationProperties) in src\GraphQL.EntityFramework\IncludeAppender.cs:line 96
at IncludeAppender.GetPaths(FieldType fieldType, ICollection`1 fields, List`1 navigationProperty) in src\GraphQL.EntityFramework\IncludeAppender.cs:line 43
at IncludeAppender.AddIncludes[T](IQueryable`1 query, FieldType fieldType, ICollection`1 subFields, List`1 navigationProperties) in src\GraphQL.EntityFramework\IncludeAppender.cs:line 29
at IncludeAppender.AddIncludes[TItem,TSource](IQueryable`1 query, ResolveFieldContext`1 context) in src\GraphQL.EntityFramework\IncludeAppender.cs:line 20
at GraphQL.EntityFramework.EfGraphQLService`1.<>c__DisplayClass21_0`2.<<BuildQueryField>b__0>d.MoveNext() in src\GraphQL.EntityFramework\GraphApi\EfGraphQLService_Queryable.cs:line 82
--- End of stack trace from previous location where exception was thrown ---
at GraphQL.Instrumentation.MiddlewareResolver.Resolve(ResolveFieldContext context)
at GraphQL.Execution.ExecutionStrategy.ExecuteNodeAsync(ExecutionContext context, ExecutionNode node)
--- End of inner exception stack trace ---"
When I step in to the code in ComplexGraphResolver I can see in GetOrAdd(FieldType fieldType)
that when it is trying to resolve the ConnectionType then resolved.EntityType
is resolved as "object".
If I use the debugger and set this to typeof(Orders) (my model type) then there is no error and my query returns correctly.
Not sure if this is an error with my config or a bug.
Add EfDocumentExecuter
to work around
Message: System.InvalidOperationException : A second operation started on this context before a previous operation completed.
To verify the assumption that there is only one match.
Hi Simon,
By passing the DataContext in on the UserContext, does this make it impossible to use authentication?
(such as nuget GraphQL.Authorization).
I am trying to implement JWT claims based authorisation, which needs to be able to access the claims via the UserContext but this happens to contain our db context instead.
Thoughts?
Many thanks,
Jeremy
When i try to select some nullable float i get this error:
{
priceHistories(ids:"230011", take:2){
monetary
quantity
priceType
priceMin
}
}
{
"errors": [
{
"message": "GraphQL.ExecutionError: Could not find conversion from System.Single to System.Double ---> System.InvalidOperationException: Could not find conversion from System.Single to System.Double\r\n at GraphQL.ValueConverter.GetConversion(Type valueType, Type targetType)\r\n at GraphQL.ValueConverter.ConvertTo(Object value, Type targetType)\r\n at GraphQL.Execution.ObjectExecutionNode.ToValue()\r\n at System.Linq.Enumerable.SelectListIterator`2.ToArray()\r\n at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)\r\n at GraphQL.Execution.ObjectExecutionNode.ToValue()\r\n at GraphQL.Execution.ExecutionStrategy.ExecuteAsync(ExecutionContext context)\r\n at GraphQL.DocumentExecuter.ExecuteAsync(ExecutionOptions options)\r\n --- End of inner exception stack trace ---",
"extensions": {
"code": "INVALID_OPERATION"
}
}
]
}
The class :
public PriceHistoryGraph(IEfGraphQLService graphQlService) : base(graphQlService)
{
Field(x => x.DateEnter, nullable: true);
Field(x => x.DateUpdate, nullable: true);
Field(x => x.Monetary, nullable: true);
Field(x => x.Operator);
Field(x => x.PriceBase, nullable: true);
Field(x => x.PriceClose, nullable: true);
Field(x => x.PriceMax, nullable: true);
Field(x => x.PriceMin, nullable: true);
Field(x => x.PriceOpen,nullable: true);
Field(x => x.PriceType, nullable: true);
Field(x => x.Quantity, nullable: true);
Field(x => x.ReportDate, nullable: true);
Field(x => x.Id);
}
public partial class PriceHistory
{
[Column("SecurityId")]
public int Id { get; set; }
public DateTime ReportDate { get; set; }
public float? PriceClose { get; set; }
public float? PriceOpen { get; set; }
public float? PriceBase { get; set; }
public float? PriceMax { get; set; }
public float? PriceMin { get; set; }
public double? Quantity { get; set; }
public double? Monetary { get; set; }
public int? TransactionsNumber { get; set; }
public int? PriceType { get; set; }
public DateTime? DateEnter { get; set; }
public DateTime? DateUpdate { get; set; }
public string Operator { get; set; }
}
Thanks.
Since they dont make sense when resoling to a single navigation instance
Filter "Property Path" doesn't work with nested List classes.
For example - you want to get Companies whose Employee id equals 5.
(Actual example would be with name, but this is simpler)
It is even be reproduced with your SampleWeb project.
You write the query
query{
companies(where: {path:"Employees.Id" comparison: equal value: "5" }){
content
employees{
id
}
}
}
It does not work.
I would expect to get All companies which have employee whose id = 5.
I've tried to fiddle around with it, I'm pretty sure the problem is in the AggregatePath
method
I tried just to make it work by a basic solution.
var strings = path.Split('.');
var firstProperty = Expression.PropertyOrField(parameter, strings.First());
var firstPropertiesItem = Expression.Property(firstProperty, "Item", Expression.Constant(0));
var actualProperty = Expression.Property(firstPropertiesItem, strings[1]);
It kind of takes the right property, but doesn't seem to work, as I'm not too familiar with ExpressionTrees.
I'm a bit new to github, so I didn't do any pull requests.
I think it is a must have to use filters over Enum types.
Added support in TypeConverter will make a PR.
There's already a similar project here: https://github.com/ckimes89/graphql-net (seems to be older than yours)
How would you compare it? Is it an alternative to the project above? Or it does something different?
Add EntityFramework Core IQueryable support to GraphQL
in readme doesn't tell much.
Also it would be helpful to have some kind of quickstart, how to get started without looking at the example project.
Hi,
This is awesome and super helpfull but can it work in combination with dataloader ?
Hi Simon,
Does it only select the fields from IQueryable like Dapper ? Dapper seems alot of coding for each resolver so it would be nice not to have to implement Dapper.
Where is the correct place to check if User has right Claims - otherwise return 401/some error message?
For example - I would like to get list of Employees only if User has claim called role: admin.
How to achieve this authorization stuff?
Thanks!
I have 2 entities (Track
and Album
) that have a many-to-many relationship via a cross table (TrackXAlbum
) which works great, but not as a navigation field.
AddNavigationField
expects the lambda to resolve with the provided type of entity given as the second generic type parameter, which can only be resolved by using a .Select
call on the IQuerable
instance returned by the Where
call.
Example on the AlbumGraph
:
AddNavigationField<TrackGraph, Track>(
"tracks",
resolve: ctx => db.TrackXAlbums.Where(e => e.AlbumId == ctx.Source.Id).Select(e => e.Track)
);
Which causes the exception:
GraphQL.ExecutionError: Error trying to resolve albums. ---> System.NullReferenceException: Object reference not set to an instance of an object.
I ended up using the AddQueryField
method instead of the AddNavigationField
. Which does work, but with a very big performance impact. Probably due to the Select
call.
How would I go about a many-to-many relationship using the AddNavigationField
method, or do I need to use a different method?
Hi Simon
Sorry but why did you put 2 times employees inside CompanyGraph:
public class CompanyGraph : EfObjectGraphType<Company>
{
public CompanyGraph(IEfGraphQLService graphQlService) : base(graphQlService)
{
Field(x => x.Id);
Field(x => x.Content);
AddNavigationField< EmployeeGraph, Employee>(
name: "employees",
resolve: context => context.Source.Employees);
AddNavigationConnectionField<EmployeeGraph, Employee>(
name: "employeesConnection",
resolve: context => context.Source.Employees,
includeNames: new []{ "Employees"});
}
}
This change clarifies the API to illustrate that only the config time IModel
is required and not a full runtime instance of DbContext
. See https://github.com/SimonCropp/GraphQL.EntityFramework/blob/master/pages/configuration.md for updated doco
TypeConverter fails to convert list of string values to list
of nullable types.
throw new Exception($"Could not convert strings to {type.FullName} ");
Line 46.
{
testEntities
(where: {
path: "NullableProperty",
comparison: "in",
value: ["Value1", "Value2"]})
{
property
}
}
TBD
Since navigation properties dont exist on the root query, the following members are redundant
FieldType AddNavigationField<TReturn>(ObjectGraphType graph,
string name,
Func<ResolveFieldContext<object>, TReturn> resolve,
Type graphType = null,
IEnumerable<QueryArgument> arguments = null,
IEnumerable<string> includeNames = null)
where TReturn : class;
FieldType AddNavigationListField<TReturn>(ObjectGraphType graph,
string name,
Func<ResolveFieldContext<object>, IEnumerable<TReturn>> resolve,
Type graphType = null,
IEnumerable<QueryArgument> arguments = null,
IEnumerable<string> includeNames = null)
where TReturn : class;
void AddNavigationConnectionField<TReturn>(
ObjectGraphType graph,
string name,
Func<ResolveFieldContext<object>, IEnumerable<TReturn>> resolve,
Type graphType = null,
IEnumerable<QueryArgument> arguments = null,
IEnumerable<string> includeNames = null,
int pageSize = 10)
where TReturn : class;
It throw expection
'Introspection must provide output type for fields.' on fields
Hi
I just started looking at graphql, and started with the core library.
I quickly went on to https://github.com/graphql-dotnet/conventions, which was pretty nice to include all types without typing them out.
But, it's not very dynamic, and therefore trying this library, and I got it working very nicely.
However, the generation of the graphtypes like the conventions library does would be nice.
Has any work been done on that? Or am I missing something?
Any hints or hurdles I may bump into that you know about?
If I make a stab at it, is depending on the conventions library the wrong way to go?
Hi,
Building works, trying to run the repo. I get
System.IO.FileLoadException: Could not load file or assembly 'System.Memory, Version=4.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference
source: "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets"
on hostBuilder.Build().Run(); in Program.cs
Hi,
i really like your implementation of query fields and query connection fields but i miss something in the middle - I need to paginate query field results, but there are no pageinfo meta for that purpose. I came from PHP (Laravel) enviroment and there pagination is implemented into GraphQL like this:
I imagine it somehow similar, query variables like this:
And inside that, it could be like this:
queryname {
items: {
.
.
.
},
totalCount
perPage
currentPage
from
to
}
What do you think about this proposal, would you merge it if i make some PR?
For my project it would be useful to convert persisted qraphql queries to linq queries in order to implement subscriptions.
Make ArgumentProcessor public.
Release separate library in order to convert GraphQl query to IQueryable.
Maybe I'm doing something horrible, but i haven't found another way to convert IQueryable to IObservable which is necessary to return from EventStreamResolvers subscribe method.
I'm currently working on a POC to implement a single GraphQL service for multiple microservices. However, I can't seem to use more than one IModel via RegisterInContainer. Looking at the code (my complements on the high quality btw!), I see only the last one is actually used. Is it technically possible to allow multiple DbContexts to be used within the same service?
Or would you suggest to use one GraphQL endpoint per microservice?
Or create one additional DbContext that contains all entities in it's IModel and use that one instead?
Thanks :)
Currently my code for GraphQL.EntityFramework
registration looks as per the guide:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
using (var context = new MyDbContext())
{
EfGraphQLConventions.RegisterInContainer(services, context);
}
services.ConfigureNSwag();
}
The thing is I am also using Autofac and would like to be able to do this registration inside one of the Autofac modules, but I've been having no success.
How am I to go about doing this? Also, is there a way to do this registration without calling the static EfGraphQLConventions.RegisterInContainer
method?
Code in startup.cs like this(modified according to sample):
var optionsBuilder = new DbContextOptionsBuilder<NHLStatsContext>(); optionsBuilder.UseMySql(Configuration["ConnectionStrings:Default"], b => b.MigrationsAssembly("NHLStats.Api")); services.AddDbContext<NHLStatsContext>(options => options.UseMySql(Configuration["ConnectionStrings:Default"], b => b.MigrationsAssembly("NHLStats.Api"))); EfGraphQLConventions.RegisterConnectionTypesInContainer(services); using (var myDataContext = new NHLStatsContext(optionsBuilder.Options)) { EfGraphQLConventions.RegisterInContainer(services, myDataContext); }
Errors:
GraphQL.EntityFramework implementation for paging with Connection model seems to use cursor sequence like "0", "1", "2", ...
Assuming a pagination with 100 items and paging with 10 items per page
I would like to implement feature like "Go directly to page 7".
Is it safe and reliable to assume I can query directly with arguments (first:10, after: X) where X is computed mathematically ?
I'm aware this is a workaround and only possible because of the cursor sequence. It would not work Facebook approach (documentation about Connection Model, show examples with base64 string for cursor : https://graphql.github.io/learn/pagination/)
Done as part of EfGraphQLConventions.RegisterInContainer((IServiceCollection, DbContext))
Premise
I'm trying to implement a root-level query field that returns a User
for the currently logged-in user. For example, I'd like to be able to make the following GraphQL request:
{
me {
fullName
profile {
id
}
}
}
Issue
AddQueryField<UserGraph, User>(
name: "me",
resolve: context =>
{
var userContext = (GraphQLUserContext)context.UserContext;
return userContext.dbContext.Users.Find(userContext.CurrentUser.Id);
});
This throws the following error:
"Cannot implicitly convert type 'CareSwitchCommon.Models.User' to 'System.Linq.IQueryable<CareSwitchCommon.Models.User>'. An explicit conversion exists (are you missing a cast?) [CareSwitchCommon]"
This suggests that AddQueryField
only works with resolve
functions that return an IQueryable
that contains lists of entities.
Attempted Solution
At this point you may say that because this field is returning a single element I should use Field()
instead of AddQueryField()
. Fair enough, so I gave that a shot and was able to make more progress:
Field<UserGraph>(
name: "me",
resolve: context =>
{
var userContext = (GraphQLUserContext)context.UserContext;
return userContext.CurrentUser
});
The problem now was getting the profile
navigation property on user to populate. This is what the relevant portions of UserGraph
look like:
public UserGraph(IEfGraphQLService graphQLService) : base(graphQLService)
{
Field(u => u.Id);
AddNavigationField<ProfileGraph, Profile>(
name: "profile",
resolve: context =>
{
return context.Source.Profile;
});
}
Specifically, it seems like context.Source.Profile
does not populate when the source is a regular field and not a query field. I was able to further hack it by doing dbContext.Entry(context.Source).Reference(u => u.Profile).Query().Single();
but that was not ideal because it leads to the n+1 sql query issue and defeats the whole purpose of the intelligent Include()
calls that GraphQL.EntityFramework is supposed to take care of.
Conclusion
It's not clear to me the best way to move forward to implement a me
query that returns EF Core data associated with the User
that's currently logged-in, and have it properly working with navigation properties.
The current implementation of the "Query" fields in this library are potentially very heavy.
Each query that eventually gets built is the equivalent of a SELECT * FROM mytable;
, instead of leveraging IQueryable and expression building to generate a "thin" select based on requested fields.
This is bad news when tables can contain very large fields (think news articles, or large file data during a "summary" query).
Build the select expressions dynamically via expression building to handle only selecting required fields from the database.
This means that the Navigation query system will need to basically be "rewritten" to account for the total change from using .Include("Navigation")
to something more akin to new { Navigation = new Navigation { ... } }
.
Possibly this can be optional on a per-query basis?
We should be able to cache the select queries in some way based on the incoming query structure, so we only have a one-time build performance hit. (Though, larger query sets, could cause potential memory consumption issues?)
I have already written code locally to handle the base "select only this table" builder, when navigation properties are not used. This vastly speeds up DB access, and dramatically lowers bandwidth requirements at the same time.
Only question is, where/how would we approach the navigation property issue?
GraphQL.NET connections require you to write a lot of boilerplate code right now. I raised an issue called How Can We Simplify Creating Connections showing said boilerplate code and one potential solution to it.
When I came across your project, I thought this is another potential solition for those using EF Core or IQueryable
in general as I don't think this project needs to be specific to EF Core. Have you considered raising a PR to contribute your AddQueryConnectionField
code in particular back to the GraphQL.NET project?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.