Reputation: 3563
From one of the 'recommendations with Neo4j' tutorials I have downloaded and imported the product catalog data set. I'm creating a Spring Neo4j project using Object Graph Mapping.
For now I have created a @NodeEntity
for both Product
and Category
. In order to quickly validate if everyting is ok used a @PostConstruct
method for a ProductService
and a CategoryService
to get a product and a category from the db.
What I notice is that if I query the product, then get the product's category, and then all the products in the category the set does not contain all products, but only the product I started the query with.
However, if I query the category itself directly it does contain all products.
The graph model is as follows:
The subset of data I'm querying on is:
The Product
entity defined as:
@NodeEntity
public class Product {
@Id
private String sku;
private String name;
@Relationship(type = "IN_CATEGORY")
private Category category;
@Convert(PriceConverter.class)
private BigDecimal price;
}
The Category
entity is defined as:
@NodeEntity
public class Category {
@Id @GeneratedValue
private Long id;
private String name;
@Relationship(type = "PARENT_CATEGORY")
private Category parent;
@Relationship(type = "IN_CATEGORY", direction = Relationship.INCOMING)
private Set<Product> products = new HashSet<>();
}
For both I have created a Repository
class.
If I query the CategoryRepository' with
categoryRepository.findByName("Desks")` and print the result this category has three products, as expected.
If I query the ProductRepository
for the "Height Adjustable Standing Desk" and print it's category information it is Category "Desks", but it only containts a single product (the Height Adjustable Standing Desk) and not the other two products.
private void showInfo(final Category category) {
System.out.printf("Name:%s%n", category.getName());
System.out.printf("Parent: %s%n", category.getParent());
System.out.printf("Products:%s%n", category.getProducts());
}
I would have expected that the set would have been lazily evaluated into the full set of products. Do I need to force it to do so? When do additional nodes get loaded into a @NodeEntity
, and how are you sure the complete subgraph for a certain node is loaded?
Edit: The documentation contains the following quote:
For graph to object mapping, the automatic transitive loading of related entities depends on the depth of the horizon specified on the call to Session.load(). The default depth of 1 implies that related node or relationship entities will be loaded and have their properties set, but none of their related entities will be populated.
Which suggests that the session object should be used to load more data, but I don't know which session object.
Upvotes: 1
Views: 87
Reputation: 2181
Your analysis is correct. The default load depth in Spring Data Neo4j (and the underlying OGM) is 1. When you load the product, you will get its category, but not other products, as these are 2 hops in the graph away from the original product. If you want to fetch all the related products, I can think of 2 possible approaches.
Having obtained the product category from the product, query the category repository with its id. This will return the list of products with that category.
Set the query depth on the original product request to 2. The default Spring Data repository methods allow you to specify the query depth. This will then return everything related to that product up to 2 hops away from it in the graph.
There is only one way to load the "complete graph" for an entity, and that is to set the query depth to -1. If your graph model is not particularly dense, this may work for you. However, it might cause performance problems in other circumstances. Also, this technique is not compatible with loading only those entities that exist in your domain model. In other words, if the graph contains nodes and relationships you don't want, setting the query depth to -1 will blindly include all of these in the query, only to discard them again before returning those that do match your domain. Again, depending on the match between your domain model and the underlying graph, this may or may not be a problem.
Please refer to https://neo4j.com/docs/ogm-manual/current/migration/#_performance_and_unlimited_load_depth for more details
Upvotes: 1