Open vfonic opened 4 years ago
It will be difficult to use deep_pluck
with GraphQL
since it have to know all selected fields including nested child fields before querying. As far as I know, we can only get one-level child fields by using lookahead feature. (I found the feature in https://github.com/rmosolgo/graphql-ruby/issues/2196 )
One possible way that may works is adding a wrapper type in the top of the types, and query all the data in it. Then use hash_key (I found the feature in https://github.com/rmosolgo/graphql-ruby/issues/107) to lookup the value from the hash via the key.
For example: (I've not tested it yet)
module Types
class UsersType < Types::BaseObject
field :users, [UserType]
def users
batch do |ids| # TODO: replace batch method by your batch querying tool.
User.where(id: ids).deep_pluck(:name, posts: [:title, :content])
# Or select all columns of the model:
# User.where(id: ids).deep_pluck(*User.column_names, posts: Post.column_names)
end
end
end
end
module Types
class UserType < Types::BaseObject
field :name, hash_key: 'name'
field :posts, [PostType], hash_key: :posts
end
end
module Types
class PostType < Types::BaseObject
field :title, hash_key: 'title'
field :content, hash_key: 'content'
end
end
It will get a huge performance improvement even if we select all columns that are not to be used, in that we only load the raw data and do not instantiate the models.
It will be difficult to use deep_pluck with GraphQL since it have to know all selected fields including nested child fields before querying. As far as I know, we can only get one-level child fields by using lookahead feature. (I found the feature in rmosolgo/graphql-ruby#2196 )
It's actually possible to get all the nested child fields using lookahead. :)
Hey @rmosolgo, do you think any of these would make sense to look further into? It doesn't have to become a standard part of 'graphql-ruby', but perhaps an extension for active record that would allow for easy performance boost (and avoiding N+1 or even multiple (batch) queries)? Do you see any downsides to this approach?
I think it would be an awesome thing to look into! It's always been "theoretically possible" but I haven't heard of anyone who actually worked it out. Please share your results if you get something working!
It will be difficult to use deep_pluck with GraphQL since it have to know all selected fields including nested child fields before querying. As far as I know, we can only get one-level child fields by using lookahead feature. (I found the feature in rmosolgo/graphql-ruby#2196 )
It's actually possible to get all the nested child fields using lookahead. :)
@vfonic I took some time to learn graphql-ruby
, and finally created a graphql
project that uses deep_pluck
to query data.
It's a very simple project while it shows it is possible to use deep_pluck
with graphql-ruby
.
See: https://github.com/khiav223577/rails-graphql-pluck-test/pull/2
I think it would be an awesome thing to look into! It's always been "theoretically possible" but I haven't heard of anyone who actually worked it out. Please share your results if you get something working!
@rmosolgo You might also be interested in it :)
Daaaamn! At first glance, this looks amazing! Thank you, @khiav223577!
When I find time, I'll try to add this to my project and let you know how it goes. I'm currently using custom method that also relies on lookahead, but queries for all the fields. This seems like a better solution.
GraphQL generally works in a way that you can query exactly the fields (columns) that you want from the database like this:
There's a very popular GraphQL gem for ruby: https://github.com/rmosolgo/graphql-ruby
Currently, the best solution that I've sees is using batch querying. It would looks something like this in reality:
Perhaps this could be optimized using
deep_pluck
? It would already be a huge improvement if it could pluck only requested fields:Note that we also need to fetch
user.id
even though that's not in the query.Any ideas how this could be achieved? Could this be something that could be done on the graphql-ruby gem perhaps?