Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Eager loading relationships #25

Open
litewarp opened this issue Jun 4, 2021 · 6 comments
Open

[Feature Request]: Eager loading relationships #25

litewarp opened this issue Jun 4, 2021 · 6 comments
Labels
feature New feature or request

Comments

@litewarp
Copy link

litewarp commented Jun 4, 2021

So I'm building a graphql layer on top of my db using neogma instead of going with the @neo4j/graphql package. One feature I've seen in a different ogm Neode is eager loading.

The code for Neode's implementation doesn't seem too advanced, especially since you've already put in logic for fetching relationships, so the big addition would be a recursion function that walks down a level or two.

Do you think this is doable? It would help gratefully in creating root resolvers that can fetch the entire tree in one db trip instead of having to break it out in to multiple requests. It's certainly not necessary though. Just a nice feature to have.

Thanks again for your package and all your help!

@tejo-ak
Copy link

tejo-ak commented Jun 4, 2021

I do that kind of query a lot. And I like to have a full control on the depth, and the structure of data object resulted from the query. Fortunately, such a feature natively supported by the cypher, using projection, something like return m {.*, likedBy: u{.*}}. One can create 'DTOs' to hold the data structure as they like it.

In doing so conveniently, I created my own wrapper for the queryRunner.run(query)

Adding a feature to fetch of relationships, and/or their related objects eagerly, could be supported as long as it won't add complexity to the api.

@litewarp litewarp closed this as completed Jun 5, 2021
@litewarp litewarp reopened this Jun 5, 2021
@litewarp
Copy link
Author

litewarp commented Jun 5, 2021

Whoops, accidentally closed and opened the issue when trying to respond to the comments above. My apologies.

Wanted to contribute and say that I agree with @tejo-ak's comments in that it is preferable to have control over the shape of the resulting schema and depth. One ideal implementation would be to have the user provide the exact shape of the fields they want during the query process by identifying the relationship aliases on the applicable Model.

const userGraph = await Users.findWithRelationships({
  relationships: {
    Friends: {
      {...filter and order args},
      relationships: {
        Enemies: {
          ... and so on
        }
      }
    }
  }
})

Then we don't have to worry about overfetching due to recursion. Plus this aligns more neatly with the 'look-ahead' GraphQL resolver strategy where one parses the info argument to get the resolvedFields and writes one query to retrieve the entire graph.

Another implementation could be the way that neode does it, where you set a flag when defining the model and then it automatically includes any flagged relationships in the base query.

@tejo-ak, would you mind sharing your wrapper implementation? It could be helpful

@themetalfleece themetalfleece added the feature New feature or request label Jun 5, 2021
@themetalfleece
Copy link
Owner

Thanks for the suggestion and all this information. This is something I have considered, but skipped due to time limitations (mostly because of the typings).
In my app, I just use the QueryBuilder.match.related as a semi-automated way to fetch nodes and relationships in a single trip.
The downside is that you manually have to group the results (i.e. with with), and get their properties from the QueryResult. However, it automates the match part of the query, both for nodes, relationships, where parameters etc.

Your suggestion is a great improvement (which is also something that's very handy and I've been using a lot on sequelize), but I don't think that I'll implement this in the near future. Or if I do implement a first version, the user might need to manually provide typings for the returned value.

@litewarp
Copy link
Author

litewarp commented Jun 5, 2021

I am admittedly not a typescript expert, but I did not think that utilizing already existing typescript relationships (e.g., we already define what the relationships are and what alias key they fall under in the model definition) would be prohibitive.

If fetching multi-level relationships will not be a feature of Neogma in the near future, could we get documentation on a work-around on how to achieve it, perhaps by the QueryBuilder.match.related method you listed above? Or perhaps Neogma isn't intended to be capable of using the model definitions to fetch more than one level of relationships, which is useful information to know before committing to it further.

@themetalfleece
Copy link
Owner

This is something that I definitely want Neogma to be capable of doing, as it will be very useful!
Since I've been using QueryBuilder.match.related a lot in my application:

  1. I can write some docs on how to use it to match multi-level relationships and parse the data from the QueryResult. Despite being more verbose, it offers a higher flexibility which comes in handy in many cases.
  2. I can implement native multi-level relationships with much more confidence, as I can see if they cover the needs and improve the current QueryBuilder implementation that I'm using.

While I can work on the documentation shortly, the native implementation won't be ready anytime soon.

@litewarp
Copy link
Author

litewarp commented Jun 5, 2021

Appreciate the response! I'm sure that the querybuilder match related function will work in the meantime but I confess I'm having a hard time figuring out how to build the query programmatically, so any examples or implementations you have would be great.

Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants