Lazy loading while adding new relation

Hi, I'm building a music advice system with Spring using neo4j.

// User Model
@Relationship (type = "LIKE", direction = OUTGOING)
private List likedArtists = new ArrayList ();

public void likeArtist (Artist artist) {
likedArtists.add (artist);
}

When i tried to like an artist, first it brings all the liked artists. Then adds it to the database. If the user likes 10.000 artists, these artists will be load to ram for every request.

Is there something I'm doing wrong?

There is nothing wrong with what you are doing. SDN/RX (I just assume that you are using it because there is an enum used for the relationship direction) is querying exactly for what you have asked (modelled) for, the User with its LIKE related Artists.
We do not plan to introduce lazy loading but in cases you do not want SDN/RX to load all Artists, you can use projection.
This means that you define a repository method that returns e.g. a UserProjection that does not define the relationship, the data won't be loaded because SDN/RX only queries for properties and relationships that are explicitly defined. Assuming you have a web application, you could also define the User's id in the projection to use it in the "show my liked artists"-view to query for the real entity.

1 Like

Thank you for your support.
But it will solve my just one problem which is when i fetch the user, liked artists won't be taken from database. My actual problem is If user send a like request, i have to use likedArtists() method so it will load all artists again.

I can solve this using native merge query but it will be much more complicated code on project. Is there any solution ?

Thanks

Hi there, I have similar problem and I commented on Repository Save/Find Depth to avoid creating new thread. However I think our best way will be to have "custom" queries. I currently do some stuff by using method which returns Flux and check for result.awaitFirstOrNull() to verify that update has been made (this is Kotlin + Webflux). In query, I return id(n), where n represents newly created something I don't care about but want to have as non-null as a proof of creation.
Example: I have buildings which should be connected to places, and on each new construction event is created, if place is in neo4j I call additional query like CREATE (place)-[relationship:HAS_PLACE]->(c) RETURN id(relationship). Your way might be non-reactive and Java which could be simple Object as return type or Long or actual creation of some node and not relationship; depending on what you really need. Also this is quite OK for me as I can do it with @Query(..) above interface method.

I still didn't get reply but I'm guessing my way of using the graph database is not so good as point of it is usually (from what I understood from Gerrit in reply above comment shared) to load part of the graph and work with it for some analytics or some other purpose or in other words: usually you want connected nodes and relationships and not just 1 node.

So since this might be the case, I guess you can try what I want to do but can't in Kotlin that easily (because of problems with @Transient on constructor parameter in data class). You can remove relationship annotation, and put @Transient on that field. Then before saving the object you can get all items from the list and persist them separately. That of course has heavy impact on your create/update actions in terms of performance but there's always a way on how to use framework and still achieve your goal if not supported directly in framework. Anyways in my project I have repository, service and a domain model as data class. Copying it is now service process as .copy uses only constructor parameters and since @Transient doesn't work on those, I had to put the member inside class and keep track of it in service. Once data is stored I take old records related objects and put them to DB where I made my own way of "upsert". Once those are in order I join back record from neo4j and list of relationships and convert it all to DTO as user response.