One node has two rels, but only return one rel when query all
Issue
One node has two rels, but only return one rel when query all.
- It is normal return, when query one use spring-data-neo4j.
- It is normal return, when query one use cql in neo4j-browser.
- It is normal return, when query all use cql in neo4j-browser.
- ** It is not normal return**, when query all use spring-data-neo4j.
query one Log (It is normal)
the node 20049 has two rels like this RECORD [node<20049>, [relationship<20044>, relationship<20043>], [node<20047>, node<20048>]] as the last line below
...
C: RUN "MATCH (s:hktxjm)
WHERE s.model = 'hktxjmmodel9' and s.idd = 'node-7f532b96-bc60-47d9-a394-ca4b5c97d7d0' AND s.nodeStatu = 'ACTIVE'
optional MATCH (s)-[r]-(t:hktxjm)
WHERE type(r) in ['guanXi']
RETURN s,collect(r), collect(t)
" {} {}
... C: PULL {n=1000}
... S: SUCCESS {t_first=1, fields=["s", "collect(r)", "collect(t)"], qid=0}
... S: RECORD [node<20049>, [relationship<20044>, relationship<20043>], [node<20047>, node<20048>]]
...
query all Log (It is not normal)
the node 20049 has two rels like this RECORD [node<20049>, [relationship<20044>, relationship<20043>], [node<20047>, node<20048>]] as the last line below, **but in return results, only one rel, the outgoingEdges list has only one element **
...
RUN "MATCH (s:hktxjm)
WHERE s.model = $model AND s.nodeStatu = 'ACTIVE'
WITH s SKIP $skip LIMIT $limit
optional MATCH (s)-[r]-(t:hktxjm)
WHERE type(r) in ['guanXi']
RETURN s,collect(r), collect(t)" {0="hktxjmmodel9", limit=100, model="hktxjmmodel9", skip=0} {}
2022-09-14 ... C: PULL {n=1000}
2022-09-14 ... S: SUCCESS {t_first=1, fields=["s", "collect(r)", "collect(t)"], qid=0}
2022-09-14 ... S: RECORD [node<20043>, [relationship<20042>, relationship<20040>, relationship<20041>], [node<20046>, node<20044>, node<20045>]]
2022-09-14 ... S: RECORD [node<20044>, [relationship<20040>], [node<20043>]]
2022-09-14 ... S: RECORD [node<20045>, [relationship<20041>], [node<20043>]]
2022-09-14 ... S: RECORD [node<20046>, [relationship<20042>], [node<20043>]]
2022-09-14 ... S: RECORD [node<20047>, [relationship<20044>], [node<20049>]]
2022-09-14 ... S: RECORD [node<20048>, [relationship<20043>], [node<20049>]]
2022-09-14 ... S: RECORD [node<20049>, [relationship<20044>, relationship<20043>], [node<20047>, node<20048>]]
...
Entity
@Node(primaryLabel="hktxjm")
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class TxjmNodeEntity extends TxjmCellEntity {
@Id
@GeneratedValue
Long id;
@NotNull
@Size(min = 1, max = 50)
// @Builder.Default
private String idd;
@NotNull
@Size(min = 1, max = 50)
private String model;
@NotNull
@ReadOnlyProperty
@Size(min = 1, max = 999)
private String nodeVersion;
@NotNull
private TxjmModel.TxjmCellStatu nodeStatu;
@NotNull
@Size(min = 1, max = 50)
private String shape;
@NotNull
@Size(min = 1, max = 50)
private String appType;
@NotNull
@Size(min = 1, max = 50)
private String defaultName;
@NotNull
@Size(min = 1, max = 50)
private String name;
@Size(max = 100)
private String description;
@CompositeProperty
// @Singular(ignoreNullCollections = true)
private Map<String, String> datas;
// @Singular(ignoreNullCollections = true)
@JsonManagedReference
@Relationship(type = "guanXi", direction = Relationship.Direction.OUTGOING)
private List<TxjmEdgeEntity> outgoingEdges;
...
import data
you can use this cql to init data
with [{shape:"hktxjm.liuCheng",appType:"fuWuRW",defaultName:"服务任务",name:"测试服务任务2",description:"测试加的内容",`datas.placeholders`:"1",`datas.parentIdd`:"",`datas.extendField`:"其它1",idd:"node-16d062f1-2b70-11ed-ba00-6c4b907924b0",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"ceDu",defaultName:"测度",name:"测试测度2",description:"测试",`datas.placeholders`:"1",`datas.parentIdd`:"",idd:"node-16d8098e-2b70-11ed-b3be-6c4b907924b0",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"quDongL",defaultName:"驱动力",name:"测试驱动力2",description:"测试",`datas.placeholders`:"1",`datas.parentIdd`:"",idd:"node-16d089ef-2b70-11ed-9832-6c4b907924b0",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"liYiXGF",defaultName:"利益相关方",name:"利益相关方",`datas.placeholders`:"1",`datas.parentIdd`:"",`datas.extendField`:"其它1",idd:"node-5c6cb4d3-857c-41d9-908f-4ae68d5da60f",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"nengLi",defaultName:"能力",name:"能力",`datas.placeholders`:"1",`datas.parentIdd`:"node-5c6cb4d3-857c-41d9-908f-4ae68d5da60f",`datas.extendField`:"其它1",idd:"node-4fef4ea8-25f7-4e9c-8a20-752e99134ec8",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"nengLi",defaultName:"能力",name:"能力",`datas.placeholders`:"1",`datas.parentIdd`:"node-5c6cb4d3-857c-41d9-908f-4ae68d5da60f",`datas.extendField`:"其它1",idd:"node-9f252924-d128-4d31-b326-0f549452519d",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"yuanJing",defaultName:"愿景",name:"愿景",`datas.placeholders`:"1",`datas.parentIdd`:"node-5c6cb4d3-857c-41d9-908f-4ae68d5da60f",`datas.extendField`:"其它1",idd:"node-7f532b96-bc60-47d9-a394-ca4b5c97d7d0",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"}] as maps, 'hktxjmmodel9' as model
unwind maps as map
MERGE (s:hktxjm { model:model, idd:map.idd, nodeStatu:'ACTIVE' })
ON CREATE SET s = map, s.model = model
ON MATCH SET s += map
RETURN s
I use new data to recheck the issue, also the problem; a->b, a->c, the query all return result is b has incoming a, c has incoming a, but a only has outgoing b, a do not include c.
I encountered the same problem,and i think the reason is org.springframework.data.neo4j.core.mapping.DefaultNeo4jEntityConverter.populateFrom(MapAccessor, NodeDescription<?>, PersistentPropertyAccessor<?>, Predicate<Neo4jPersistentProperty>, boolean, Collection<Relationship>, Collection<Node>) avoid unnecessary re-assignment of values
Could you create a database setup including the relationships? I tried to reproduce it on with the data from #2583 and also added the definition of the incoming relationships to the model. But all seems fine (for samples I thought it was worth looking at them). Would be good to get the problematic subset to figure out the problem.
Sorry, forget to paste relationsips cql; I will give you a new simpler data(only 3 nodes and 2 rels) to test as below create node
with [{shape:"hktxjm.zhanLue",appType:"ceDu",defaultName:"测度",name:"testCeDu1",description:"test",`datas.extendField`:"test",idd:"node-6edd138d-03e6-4b15-8cd2-4c2e930b75f1",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.zhanLue",appType:"ceDu",defaultName:"测度",name:"testCeDu2",description:"test2",`datas.extendField`:"test2",idd:"node-7c067fa8-50f7-47df-b43a-1e41c0c4006d",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"},{shape:"hktxjm.yingYong",appType:"yingYongY",defaultName:"域",name:"testYingYongY1",idd:"node-41498c56-7f82-4444-927a-39e73fc1bfa1",nodeVersion:"1",model:"hktxjmmodel9",nodeStatu:"ACTIVE"}] as maps, 'hktxjmmodel9' as model
unwind maps as map
MERGE (s:hktxjm { model:model, idd:map.idd, nodeStatu:'ACTIVE' })
ON CREATE SET s = map, s.model = model
ON MATCH SET s += map
RETURN s
create relationship
with [{sourceNodeIdd:"node-6edd138d-03e6-4b15-8cd2-4c2e930b75f1",targetNodeIdd:"node-41498c56-7f82-4444-927a-39e73fc1bfa1",edgeIdd:"edge-93e6c4f8-f06e-4136-835a-69d7d5f5696b",edgeMap:{shape:"hktxjm.guanXi",appType:"parent",defaultName:"父",name:"testParent1",idd:"edge-93e6c4f8-f06e-4136-835a-69d7d5f5696b"}},{sourceNodeIdd:"node-7c067fa8-50f7-47df-b43a-1e41c0c4006d",targetNodeIdd:"node-41498c56-7f82-4444-927a-39e73fc1bfa1",edgeIdd:"edge-7503965e-c9fa-4547-aba1-6a6df16c67cd",edgeMap:{shape:"hktxjm.guanXi",appType:"parent",defaultName:"父",name:"testParent2",idd:"edge-7503965e-c9fa-4547-aba1-6a6df16c67cd"}}] as lists, 'hktxjmmodel9' as model
unwind lists as item
MATCH (s:hktxjm { model:model, idd:item.sourceNodeIdd, nodeStatu:'ACTIVE' })
MATCH (t:hktxjm { model:model, idd:item.targetNodeIdd, nodeStatu:'ACTIVE' })
MERGE (s)-[r:guanXi {idd:item.edgeIdd}]->(t)
ON CREATE SET r = item.edgeMap
ON MATCH SET r += item.edgeMap
WITH item,model,s,r,t
MATCH(s2:hktxjm { model:model})-[r2:guanXi {idd:item.edgeIdd}]->(t2:hktxjm { model:model})
WHERE s.idd <> s2.idd or t.idd <> t2.idd
DELETE r2
RETURN s,collect(r),collect(t)
test findone(by node idd=node-41498c56-7f82-4444-927a-39e73fc1bfa1) it is normal has 2 incoming rels the result is :
{
"cell": "yingYongY",
"name": "testYingYongY1",
"description": null,
"datas": {},
"idd": "node-41498c56-7f82-4444-927a-39e73fc1bfa1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": [
{
"cell": "parent",
"name": "testParent2",
"description": null,
"datas": {},
"idd": "edge-7503965e-c9fa-4547-aba1-6a6df16c67cd",
"otherSideNode": {
"cell": "ceDu",
"name": "testCeDu2",
"description": "test2",
"datas": {
"extendField": "test2"
},
"idd": "node-7c067fa8-50f7-47df-b43a-1e41c0c4006d",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": null,
"banBenEdges": null
}
},
{
"cell": "parent",
"name": "testParent1",
"description": null,
"datas": {},
"idd": "edge-93e6c4f8-f06e-4136-835a-69d7d5f5696b",
"otherSideNode": {
"cell": "ceDu",
"name": "testCeDu1",
"description": "test",
"datas": {
"extendField": "test"
},
"idd": "node-6edd138d-03e6-4b15-8cd2-4c2e930b75f1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": null,
"banBenEdges": null
}
}
],
"outgoingEdges": null,
"banBenEdges": null
}
test findAll, it is not normal, the node(idd=node-41498c56-7f82-4444-927a-39e73fc1bfa1) has only one incoming rel the result is :
{
"content": [
{
"cell": "ceDu",
"name": "testCeDu1",
"description": "test",
"datas": {
"extendField": "test"
},
"idd": "node-6edd138d-03e6-4b15-8cd2-4c2e930b75f1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": [
{
"cell": "parent",
"name": "testParent1",
"description": null,
"datas": {},
"idd": "edge-93e6c4f8-f06e-4136-835a-69d7d5f5696b",
"otherSideNode": {
"cell": "yingYongY",
"name": "testYingYongY1",
"description": null,
"datas": {},
"idd": "node-41498c56-7f82-4444-927a-39e73fc1bfa1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": null,
"banBenEdges": null
}
}
],
"banBenEdges": null
},
{
"cell": "ceDu",
"name": "testCeDu2",
"description": "test2",
"datas": {
"extendField": "test2"
},
"idd": "node-7c067fa8-50f7-47df-b43a-1e41c0c4006d",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": [
{
"cell": "parent",
"name": "testParent2",
"description": null,
"datas": {},
"idd": "edge-7503965e-c9fa-4547-aba1-6a6df16c67cd",
"otherSideNode": {
"cell": "yingYongY",
"name": "testYingYongY1",
"description": null,
"datas": {},
"idd": "node-41498c56-7f82-4444-927a-39e73fc1bfa1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": null,
"banBenEdges": null
}
}
],
"banBenEdges": null
},
{
"cell": "yingYongY",
"name": "testYingYongY1",
"description": null,
"datas": {},
"idd": "node-41498c56-7f82-4444-927a-39e73fc1bfa1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": [
{
"cell": "parent",
"name": "testParent1",
"description": null,
"datas": {},
"idd": "edge-93e6c4f8-f06e-4136-835a-69d7d5f5696b",
"otherSideNode": {
"cell": "ceDu",
"name": "testCeDu1",
"description": "test",
"datas": {
"extendField": "test"
},
"idd": "node-6edd138d-03e6-4b15-8cd2-4c2e930b75f1",
"model": "hktxjmmodel9",
"nodeVersion": "1",
"nodeStatu": "ACTIVE",
"incomingEdges": null,
"outgoingEdges": null,
"banBenEdges": null
}
}
],
"outgoingEdges": null,
"banBenEdges": null
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageSize": 20,
"pageNumber": 0,
"unpaged": false,
"paged": true
},
"last": true,
"totalElements": 3,
"totalPages": 1,
"size": 20,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"first": true,
"numberOfElements": 3,
"empty": false
}
@meistermeier hi, Has the problem recurred?
Unfortunately to get down to this issue, I was not able to reproduce the problem. Can you please report the SDN version, you are using when observing the issue?
I also ran the following test multiple (a thousand) times for single and all results.
@Test
void testIncomingEdges() {
// var entity = repository.findByIdd("node-41498c56-7f82-4444-927a-39e73fc1bfa1");
var entities = repository.findAll();
var entity = entities.stream().filter(s -> s.getIdd().equals("node-41498c56-7f82-4444-927a-39e73fc1bfa1")).findFirst().get();
Assertions.assertThat(entity.getEdgeIncoming()).hasSize(2);
}
@meistermeier Sorry, I not provide sufficient details. the sdn is:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
<version>2.7.2</version>
</dependency>
The findAll repository code is used custom query:
Optional<TxjmNodeEntity> findOneByModelAndIdd(String model, String idd);
List<TxjmNodeEntity> findAllByModel(String model);
@Transactional(readOnly = true)
@Query(value = "MATCH (s:hktxjm)\n" +
"WHERE s.model = $model AND s.nodeStatu = 'ACTIVE' \n" +
"WITH s :#{orderBy(#pageable)} SKIP $skip LIMIT $limit \n" +
"optional MATCH (s)-[r]-(t:hktxjm)\n" +
"WHERE type(r) in ['guanXi']\n" +
"RETURN s,collect(r), collect(t)",
countQuery = "MATCH (s:hktxjm)\n" +
"WHERE s.model = $model AND s.nodeStatu = 'ACTIVE' \n" +
"RETURN count(s)"
)
Page<TxjmNodeEntity> queryAllNodes(String model, Pageable pageable);
The test code is:
@Test
void testFindOne() {
String model = "hktxjmmodel9";
//findOne
Optional<TxjmNodeEntity> entityForFindOne = txjmNodeEntityRepository.findOneByModelAndIdd(model,"node-41498c56-7f82-4444-927a-39e73fc1bfa1");
Assertions.assertThat(entityForFindOne.get().getIncomingEdges()).hasSize(2);
}
@Test
void testFindAll() {
String model = "hktxjmmodel9";
//findAll
List<TxjmNodeEntity> entitiesForFindAll = txjmNodeEntityRepository.findAllByModel(model);
TxjmNodeEntity entityFromFindAll = entitiesForFindAll.stream().filter(s -> s.getIdd().equals("node-41498c56-7f82-4444-927a-39e73fc1bfa1")).findFirst().get();
Assertions.assertThat(entityFromFindAll.getIncomingEdges()).hasSize(2);
}
@Test
void testCustomQueryAll() {
String model = "hktxjmmodel9";
//costum query all
Page<TxjmNodeEntity> entitiesForCustomQueryAll = txjmNodeEntityRepository.queryAllNodes(model, Pageable.ofSize(20));
TxjmNodeEntity entityFromCustomQueryAll = entitiesForCustomQueryAll.stream().filter(s -> s.getIdd().equals("node-41498c56-7f82-4444-927a-39e73fc1bfa1")).findFirst().get();
Assertions.assertThat(entityFromCustomQueryAll.getIncomingEdges()).hasSize(2);
}
The test result is :

That's interesting, I tried to reproduce it but still no chance. I created a (non-)reproducer https://github.com/meistermeier/neo4j-issues-examples/tree/master/gh-2592 It might be worth a look what I am doing different/wrong.
@meistermeier hi, i add a new test fun in https://github.com/meistermeier/neo4j-issues-examples/pull/4, it is fail. I want to try new snapshot version you mentioned in #2600 ,but I cannot get the 6.3.4 version.
The version is 6.3.4-GH-2600-SNAPSHOT not just 6.3.4.
Also you need to define Spring's snapshot (and milestone) repositories.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>6.3.4-GH-2600-SNAPSHOT</version>
</dependency>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
with this in place, the test runs smoothly.
@meistermeier Hi, The test passed when I use the new snapshot version you provided. Thanks a lot. Looking forward to the release of the new Release version.
Thank you very much for your feedback. I will close this issue now and keep #2600 to have a single reference issue for the fix.