Neo4j / Cypher: Match nodes only if they have a relation with 1 or more other nodes

戏子无情 提交于 2019-12-13 03:32:21

问题


I'm having some trouble on this query I am trying to build. I have looked plenty of places over the internet and I couldn't seem to find an answer, so I am asking here.

so here is what my schema somewhat looks like. (sorry for shitty paint diagram)

The query I want is;

Starting from one Route node, I get multiple RS, and a single OMS from each RS

I want to find all Route nodes which eventually connects to the same (or more) OMS nodes

here is my current query:

MATCH (st)--(rs:RS)--(oms:OMS)
WHERE id(st) = 0
with st,rs, oms, collect(oms) as omsn

MATCH (ed:Route)--(rs2:RS)
WHERE ALL(x in omsn WHERE (ed)--(rs2)--(x))

RETURN *

And that returns this.

Which is almost correct, but notice that Route node 21 does not connect to BOTH OMS 4 and 2 so I do NOT want that strand

The result should be something like this instead.

How would I change my query to accomplish this instead? (Note that the RS node in the middle is necessary for some other stuff I am also doing, so I cannot remove those. I have gotten it working, though with just a 2 layer heiarchy, but that is not what I need.)

edit: simple insertion query

CREATE (a:Route)-[:rel]->(b:RS)-[:rel]->(c:OMS)

CREATE (a)-[:rel]->(d:RS)-[:rel]->(e:OMS)

CREATE (f:Route)-[:rel]->(g:RS)-[:rel]->(c)
CREATE (f)-[:rel]->(i:RS)-[:rel]->(e)
CREATE (f)-[:rel]->(k:RS)-[:rel]->(hfg:OMS)

CREATE (l:Route)-[:rel]->(m:RS)-[:rel]->(c)
CREATE (l)-[:rel]->(o:RS)-[:rel]->(e)
CREATE (l)-[:rel]->(asd:RS)-[:rel]->(dsf:OMS)
CREATE (l)-[:rel]->(ds:RS)-[:rel]->(gdg:OMS)

MATCH (m:OMS) WHERE id(m) = 4
CREATE (:Route)-[:rel]->(:RS)-[:rel]->(m)

RETURN *

回答1:


2 tips for working with Cypher.

1) Run a test with RETURN * after each WITH to verify you are returning what you want.

2) Look at the text table to verify the format of your return data.

The problem with your query is this part

MATCH (st)--(rs:RS)--(oms:OMS)
WHERE id(st) = 0
with st,rs, oms, collect(oms) as omsn
  • (st) is a single node, so 1 row of data
  • (rs) is two diffrent nodes, so now you have 2 rows of data
  • each (oms) node is one node off of an (rs) node. So 1 row for each (rs).
  • RETURN * will return 1 * 2 * COLLECT(1) as 1 = 2 rows
    • Note here that you have 2 rows of data, each with 1 distinct (oms) node

The solution here is to either do

  • Use COLLECT(rs) in the WITH to collapse those 2 rows into 1, so that the 2 (oms) nodes also get collected into the same list (note, this may contain duplicate oms nodes. use COLLECT(DISTINCT oms) if this will be a problem)
  • Only carry over COLLECT(oms) in the WITH part. The rest will be matched again in the following match anyways.

Final note. You know the direction of the relationships; Include it in the Cypher for better/cleaner performance.



来源:https://stackoverflow.com/questions/50804968/neo4j-cypher-match-nodes-only-if-they-have-a-relation-with-1-or-more-other-no

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!