activegraph
activegraph copied to clipboard
Think about ways to return specific fields on nodes
Would be nice to be able to say what fields that you want to return in specific cases and have ActiveNode / ActiveRel populated objects. I was returning some nodes and there was a large text field that I wasn't using in a particular request.
- We could have it happen when building a query
Model.with_properties(:prop1, :prop2).find(id)
- We could define that properties are lazy loaded
property :prop1, lazy_load: true
and then specify later either on the object or as part of the thing that will make the query that we want to load that property - We also may want to consider always only loading the properties on the model
This would probably make the Cypher queries uglier...
@cheerfulstoic I see this to be important from performance perspective as well, in the video by Mark Needham and Petra Selmer on 'Tuning your Cypher' over at http://graphconnect.com/, they state that rather than returning all node properties, if you pick specific properties, the queries are expected to perform better.
I don't think there is a way to do something "clean" considering how Cypher works but I see an "quite easy" to implement solution
MyModel.query_as(:m).return('collect({name: m.name, slug: m.slug, label: 'MyModel'}')
This way we could "fake" the label and force neo4jrb to hydrate the collection accordingly.
Another solution (a bit more complicated) would be to match query_as
and fields name :
MyModel.query_as(:m).return('ID(m), m.uuid, m.id, m.name, m.slug, COUNT(relations) as count').each_with_hydration do |row|
row['m.slug'] # would be the slug
row['m'] # would be "auto hydrated" into a <#MyModel>
end
This could work with the each
method but it would have too many side effects in my opinion, so creating a new method seems better.
I need this feature too, so I'll try to take a look to see if it's possible to make this work.
I have thought about the solution of having Maps like the suggestion in your first comment. My hesitance about that has been that when you return nodes / relationships from Neo4j, you don't get a map but rather a more complex object to describe said nodes / relationships. In order to support this we'd need two different paths to wrap nodes.
I've generally been able to get around this by just doing a pluck
and getting the attributes that I need, though I realize that's not as nice. Though I do wonder about the potential confusion of having situations where objects have been hydrated from the database without all the properties. I could easily picture developers coming along behind and being super confused.
Another way that I've dealt with this is to define a method on Query
called pluck_struct
which takes in a ruby Struct
and which maps it's members to fields which are being returned. It then plucks those properties and hydrates objects of the Struct
. This doesn't give you validations / associations / etc..., but it does make it pretty clear that you're not dealing with a model object. It also has the advantage that you can build objects which are aggregations of multiple different nodes / relationships which are appropriate to the particular query.