Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

EAGER annotation on node relations #121

Open
theUm opened this issue Apr 3, 2017 · 8 comments
Open

EAGER annotation on node relations #121

theUm opened this issue Apr 3, 2017 · 8 comments

Comments

@theUm
Copy link
Contributor

theUm commented Apr 3, 2017

If we have @LAZY, we need doctrine like @EAGER too. In some cases it will be wery usefull to have autoloaded relations.

Example case: I have labels "Object", "FieldType", "Value" they are all interlinked. So whenever I want to make list of object values with corresponded field types, I must gather values from object, then get field types from object from other relation type, and then link values to types through foreach. Its very frustrating to do so, and prefetching field types with fields would be nice thing to have.

@ikwattro
Copy link
Member

ikwattro commented Apr 3, 2017

@theUm couldn't this be solved with using createQuery() (when improved of course).

I see two benefits to this :

  1. It forces people to learn cypher and not blindly rely on an ogm
  2. It avoids undesired effects, what if people add EAGER and a node is very dense

However I'm not sure I understand fully this part :

I must gather values from object, then get field types from object from other relation type, and then link values to types through foreac

@theUm
Copy link
Contributor Author

theUm commented Apr 3, 2017

  1. Sure, CreateQuery may solve everithing. But I want to build system that will be twig-friendly as possible. The finished project structure must be simple to use as it could be. In my case I have dynamic structure for nodes, and cant just write fast and relieble CreateQuery. Thats why I think EAGER is good thing, it helps in very specific use cases, but in this cases it has huge impact.

Ok. I'll show you full case of my structure:
I have 4 node labels that represents dynamic structure for data storing:
graph_structure
when I want to show Object on its own page,
1:) I fetch THE_OBJECT at first: $theObject = $objectRepository->findOneBy([someth])
2:) then I want to show all it fields and field types: $theObject->getFieldValues()
At this point I have a collection of FieldValue nodes as values of THE_OBJECT fields.
3.) Next thing to do is sort FieldValues by TypeFields (TypeField is node represents field type and config).
So I can do two things:

  • foreach ($object->->getFieldValues() as $val){ $val->getTypeField(); } which will result in extra query per fieldValue which will be horrific for speed and common sense :)
  • make CreateQuery. Something like MATCH (et)<--(o:Object)<--(fv:FieldValue)-->(etf:EntityTypeField)-->(et) WHERE o.slug = 'someth' RETURN {type:etf.slug, fields: collect(fv)} wich is`nt working now for me because I cant manage to map result properly (related to #120)

So with EAGER I sipmly can go first way and do not worry about performance because all FieldValues
will already have their EntityTypeFields loaded.

@ikwattro
Copy link
Member

ikwattro commented Apr 3, 2017

I agree it makes sense.

The only problem I have with the @Eager annotation is that you wouldn't have the possibility to specify don't eager load but that's fair.

For your use case though, I would personally do the following :

  • Use createQuery() when it will support that type of queries :)

or

  • Use a label representing the type of the field on the FieldValue node, like the current @Label annotation but with user defined logic, when it will work :)

I leave the issue open without saying no, however I think createQuery() functionality as well as custom labels are more important than Eager for a GA release.

@theUm
Copy link
Contributor Author

theUm commented Apr 4, 2017

Thanks for answer. I'll wait for createQuery() updates - the label approach is not siutable for my use case - FieldTypes are dynamic too ;) Everithing is dynamic in my use case, code is just set of restrictions on links between nodes in DB and CRUD mechanics. Thats the reason for me to choose neo4j and I'm happy with it :)

@mfalcier
Copy link

mfalcier commented Apr 5, 2017

What if eagerness could be controller by defining a maximum depth level?
This could partially resolve some hypothetical dense loads.

@theUm
Copy link
Contributor Author

theUm commented Apr 5, 2017

Max depth level? This means we should know and define eagerness path. Isn`t it will be too complex to implement and maintain? What to do with circular references? What will be syntax to such eager annotations?
My personal opinion is thats will be step back (when ogm tried to load all at once ;) ). Way more usefull, but yet dangerous will be recursive eagerness. But what if we need to have eagerness in one case and do not want in other? May be ArrayCollection should have special methods for that specific cases?

@ikwattro
Copy link
Member

ikwattro commented Apr 5, 2017

@mfalcier when we speak about dense is that for example a Twitter user could have 1 million followers.

@theUm The java ogm uses depth fetching by default, when you load entities you defined until which depth you want to fetch. To be honest, I see how they are struggling and this isn't something I'm gonna implement.

However combining depth with EAGER can be interesting, for example you could be able to load all depth 2 entities at once starting from your "THE OBJECT" node. Anyway I'm afraid EAGER will be post-ga.

@SavageDan
Copy link

There's an additional option that can be applied with eager loading, which is the idea of Laravel's 'With' clause in calling relationships. It would be nice to be able to specify which relationships we want to load with a node so that we don't have to keep querying the database for more data to return.

For instance, let's say we have a user and they have a relationship to their pets. If we act normally, if we want to know the pet's name, we have to make another call to the database to get the pet information.

However if we specify something like user->with(pet::class) then it will eager load that user with the pet nodes as well, meaning we can make one call to the database instead of several.

This is a simpler implementation and should help avoid the very real situations of recursive relationships and loading by depth, provided this is managed well enough.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants