-
Notifications
You must be signed in to change notification settings - Fork 617
Improve documentation for hydrating collections based on queries returning paths. #2210
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
Comments
Did this work with 6.0.6? |
Oh, I guess I see what you want to achieve… Here's a test for the standard finders with your model. Does this clear things up? /*
* Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.integration.issues.gh2210;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Optional;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.AbstractNeo4jConfig;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.test.Neo4jExtension;
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author Michael J. Simons
*/
@Neo4jIntegrationTest
class GH2210IT {
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
@BeforeAll
protected static void setupData() {
try (Transaction transaction = neo4jConnectionSupport.getDriver().session().beginTransaction()) {
transaction.run("MATCH (n) detach delete n");
transaction.run("create (a:SomeEntity {number:1, name: \"A\"})\n"
+ "create (b:SomeEntity {number:2, name: \"B\"})\n"
+ "create (c:SomeEntity {number:3, name: \"C\"})\n"
+ "create (d:SomeEntity {number:4, name: \"D\"})\n"
+ "create (a) -[:SOME_RELATION_TO {someData: \"d1\"}] -> (b)\n"
+ "create (b) <-[:SOME_RELATION_TO {someData: \"d2\"}] - (c)\n"
+ "create (c) <-[:SOME_RELATION_TO {someData: \"d3\"}] - (d)\n"
+ "return * ");
transaction.commit();
}
}
@Test // GH-2210
void standardFinderShouldWork(@Autowired SomeRepository someRepository) {
Optional<SomeEntity> a = someRepository.findById(1L);
assertThat(a).hasValueSatisfying(s -> {
assertThat(s.getName()).isEqualTo("A");
assertThat(s.getSomeRelationsOut())
.hasSize(1)
.first().satisfies(b -> {
assertThat(b.getSomeData()).isEqualTo("d1");
assertThat(b.getTargetPerson().getName()).isEqualTo("B");
assertThat(b.getTargetPerson().getSomeRelationsOut()).isEmpty();
});
});
Optional<SomeEntity> d = someRepository.findById(4L);
assertThat(d).hasValueSatisfying(s -> {
assertThat(s.getName()).isEqualTo("D");
assertThat(s.getSomeRelationsOut())
.hasSize(1)
.first().satisfies(c -> {
assertThat(c.getSomeData()).isEqualTo("d3");
assertThat(c.getTargetPerson().getName()).isEqualTo("C");
assertThat(c.getTargetPerson().getSomeRelationsOut())
.hasSize(1)
.first().satisfies(b -> {
assertThat(b.getSomeData()).isEqualTo("d2");
assertThat(b.getTargetPerson().getName()).isEqualTo("B");
assertThat(b.getTargetPerson().getSomeRelationsOut()).isEmpty();
});
});
});
}
interface SomeRepository extends Neo4jRepository<SomeEntity, Long> {
}
@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(considerNestedRepositories = true)
static class Config extends AbstractNeo4jConfig {
@Bean
public Driver driver() {
return neo4jConnectionSupport.getDriver();
}
}
} |
It didn't work with 6.0.6 either. The test uses findById, and it has the behavior I would expect when querying for a single node: the Java object only stores outgoing relationships, so we lose/don't see any incoming ones. (It would be nice to get both incoming and outgoing relations, but that's another discussion). When querying for paths, I would expect the returned List of Nodes to be populated with all the nodes found in each path and hydrated with the distinct relationships of each path (since Neo4j returns all that data in the query). Instead, it seems to build the List starting from the "root" node, which hits a dead end if all the relationships are incoming (and your Java object only stores outgoing). |
Well, after thinking some more a "list of paths" doesn't make sense, since a list can only contain one path. Maybe a list of lists with one path each would make more sense. Ultimately, my problem seems to come down to a lack of having both incoming and outgoing relations on a given Node entity. Otherwise I could follow either direction to explore the returned paths. |
Thanks already very much for your detailed thoughts and explanation.
Let me recap: the result of ur custom query is populated like it would be
with the standard one. But as u selected everything u expect it to be used.
That would require no small changes in our mapping code but I do understand
the thinking behind it and will add my own after the Easter holidays.
Ben Bohannon ***@***.***> schrieb am Fr. 2. Apr. 2021 um
16:10:
… Well, after thinking some more a "list of paths" doesn't make sense, since
a list can only contain one path. Maybe a list of lists with one path each
would make more sense.
Ultimately, my problem seems to come down to a lack of having both
incoming and outgoing relations on a given Node entity. Otherwise I could
follow either direction to explore the returned paths.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2210 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEAQL6UQU3XFSMEG7YR4ITTGXF5VANCNFSM42HXLT3Q>
.
|
Your use case will work when you write your query slightly different and return the path: String query = "MATCH p = (leaf:SomeEntity {number: $a})-[:SOME_RELATION_TO*]-(:SomeEntity) RETURN p"; I am gonna update that part of the docs for this use case: https://docs.spring.io/spring-data/neo4j/docs/6.1.0/reference/html/#faq.path-mapping |
…eries returning paths. This closes #2210.
…eries returning paths. This closes #2210.
On 6.0.7, I'm trying to use a custom query like this:
to get all paths from a single PERSON node to all other PERSON nodes connected by SOME_RELATION_TO regardless of direction or depth, and I also need the relationship properties between each node.
Entities:
My problem is that performing this query from a leaf node (only incoming directions) yields a list containing only the leaf node without any other relationships (since it technically has none outgoing?). The query only returns other nodes/relationships when performed from a node with outgoing directions.
My graph is acylic and only composed of a single node and relation type.
E.g. Person A -> Person B <- Person C <- Person D
If the query is performed from Person A, then I only get Persons A and B. If performed from Person B, then I only get Person B.
Should my query be different? Or is this a limitation of the object mapping or bi-directional relationships?
The text was updated successfully, but these errors were encountered: