Neo4j Cypher заявка - събира елементи от 2 различни променливи в един списък

Имам следната част от заявката за Cypher:

MATCH (ch:Characteristic) WHERE id(ch) = {characteristicId} WITH ch OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)...

първо търся (ch:Characteristic) от characteristicId и след това прилагам необходимата логика за тази променлива в останалата част от моята заявка.

моят Characteristic също може да има (или не) дъщерни Characteristic възли, като:

(ch:Characteristic)-[:CONTAINS]->(childCh)

Моля, помогнете ми да разширя заявката си, за да събера ch и childCh в списък от Characteristic, така че ще мога в останалата част от заявката си да приложа необходимата логика към всички Characteristic в този списък.

АКТУАЛИЗИРАНО - възможно решение №2

Това е текущата ми работна заявка:

MATCH (chparent:Characteristic) 
WHERE id(chparent) = {characteristicId} 
OPTIONAL MATCH (chparent)-[:CONTAINS*]->(chchild:Characteristic) 
WITH chparent, collect(distinct(chchild)) as childs 
WITH childs + chparent as nodes 
UNWIND nodes as ch 
OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(Decision) 
OPTIONAL MATCH (v)-[:CONTAINS]->(vE) OPTIONAL MATCH (vE)-[:CONTAINS]->(vEE) 
OPTIONAL MATCH (ch)-[:CONTAINS]->(cho:CharacteristicOption) 
OPTIONAL MATCH (cho)-[:CONTAINS]->(choE) OPTIONAL MATCH (ch)-[:CONTAINS]->(chE) 
DETACH DELETE choE, cho, ch, vEE, vE, v, chE

Това е опит за опростяване на заявката по-горе:

MATCH (ch:Characteristic) 
WHERE (:Characteristic {id: {characteristicId}})-[:CONTAINS*]->(ch) 
OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(Decision) 
OPTIONAL MATCH (v)-[:CONTAINS]->(vE) 
OPTIONAL MATCH (vE)-[:CONTAINS]->(vEE) 
OPTIONAL MATCH (ch)-[:CONTAINS]->(cho:CharacteristicOption) 
OPTIONAL MATCH (cho)-[:CONTAINS]->(choE) 
OPTIONAL MATCH (ch)-[:CONTAINS]->(chE) 
DETACH DELETE choE, cho, ch, vEE, vE, v, chE

но тази заявка не изтрива необходимите възли на Характеристика и моите тестове се провалят. Какво правя погрешно при последното запитване?


person alexanoid    schedule 21.05.2017    source източник
comment
опитайте С chparent + childs като ch UNWIND ch като възли OPTIONAL MATCH (nodes)‹-[:SET_ON].... По принцип получавате списък с възли с collect и сега трябва да UNWIND списъка, който е като .map в JS, или като forEach, където правите няколко оптимални съвпадения за всеки възел в списъка (колекцията).   -  person Tomaž Bratanič    schedule 21.05.2017
comment
Благодаря ти ! Сега работи според очакванията.   -  person alexanoid    schedule 21.05.2017
comment
В опита си да опростите заявката, вие се опитвате да намерите съответствие в свойството id, но това не е същото като вътрешния neo4j id в работната заявка. Трябва да използвате функцията id(), за да получите или сравните вътрешните идентификатори на neo4j.   -  person InverseFalcon    schedule 22.05.2017
comment
Благодаря, по този начин се връщаме към заявката като тази MATCH (chparent)-[:CONTAINS*0..]->(ch:Characteristic) WHERE id(chparent) = {characteristicId} и тя се проваля с грешка, която показах като коментар към вашия отговор - Caused by: org.neo4j.kernel.api.exceptions.EntityNotFoundException: Unable to load NODE with id 827. :(   -  person alexanoid    schedule 22.05.2017


Отговори (4)


Можете да опитате нещо подобно с apoc:

MATCH (chparent:Characteristic {characteristicId: <someid>})
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH apoc.coll.union(chparent,chchild) as distinctList
...

С чист cypher можете да опитате нещо подобно:

MATCH (chparent:Characteristic {characteristicId: <someid>})
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH chparent,collect(distinct(chchild)) as childs
WITH chparent + childs as list
....

Не съм много сигурен дали имате нужда от различен in collect, но добавих, за да знаете, че можете да направите това, за да филтрирате дубликати.

person Tomaž Bratanič    schedule 21.05.2017
comment
Благодаря. Никога преди не съм използвал функцията apoc. Опитах се да изпълня заявката на моя Neo4j Embedded 3.1.3 и не успя със следната грешка: Unknown function 'apoc.coll.union' - person alexanoid; 21.05.2017
comment
добре, той не идва с Neo4j, трябва да го инсталирате ръчно... има начин да направите това само с Cypher, нека го намеря и актуализирам отговора - person Tomaž Bratanič; 21.05.2017
comment
Също така се опитах да добавя <dependency> <groupId>org.neo4j.procedure</groupId> <artifactId>apoc</artifactId> <version>3.1.3.7</version> <scope>test</scope> </dependency> в моя Maven pom.xml, но все още не работи - person alexanoid; 21.05.2017
comment
вижте това stackoverflow.com/questions/43965481/ - person Tomaž Bratanič; 21.05.2017

Всъщност можете да направите това лесно, като използвате съвпадение на връзка с променлива дължина на 0..1, тъй като това ще ви позволи да съпоставите вашия основен : характерен възел и всяко от неговите деца.

MATCH (chparent:Characteristic)-[:CONTAINS*0..1]->(ch:Characteristic)
WHERE id(chparent) = {characteristicId} 
// ch contains both the parent and children, no need for a list
...
person InverseFalcon    schedule 21.05.2017
comment
Благодаря. Ще върне ли поне chparent възел в случай, че няма деца (ch)? - person alexanoid; 21.05.2017
comment
Да, тъй като ако възелът chparent съществува, той поне ще може да съпостави себе си. - person InverseFalcon; 21.05.2017
comment
Съжалявам за още един глупав въпрос, но тази заявка ще върне ли всички наследствени възли с каквато и да е дълбочина или само директни деца на chparent? - person alexanoid; 21.05.2017
comment
Промених заявката на MATCH (chparent)-[:CONTAINS*0..1]->(ch:Characteristic) WHERE id(chparent) = {characteristicId} OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)... и тя се проваля в момента с Caused by: org.neo4j.cypher.EntityNotFoundException: Node with id 5203 has been deleted in this transaction - person alexanoid; 21.05.2017
comment
Това е ново. Нямате DETACH DELETEs в заявката си преди това? Каква версия на Neo4j използвате и правите заявки през браузъра или от друга система? - person InverseFalcon; 21.05.2017
comment
И що се отнася до дълбочината, *0..1 е само самият възел или непосредствено свързаните. Можете да посочите различна горна граница, ако искате това на по-голяма дълбочина, или да използвате *0.. за липса на горна граница. - person InverseFalcon; 21.05.2017
comment
Благодаря. Имам само DETACH DELETE в края на моята заявка и използвам Neo4j 3.1.3. В момента го тествам чрез SDN 4/OGM Neo4j Embedded от моите тестове. - person alexanoid; 21.05.2017
comment
Актуализирах въпроса си с повече подробности - текуща работеща заявка срещу опит да я опростя. какво правя грешно - person alexanoid; 22.05.2017

По-опростена заявка.

MATCH (c:Characteristics) WHERE (:Characteristics {id: 123})-[:CONTAINS*0..1]->(c) return c;

Съвпада с всички характеристики, включително основния възел, който (по избор) има входящи връзки от тип CONTAINS от възела, посочен с id 123.

person bjornbergq    schedule 22.05.2017
comment
Благодаря. Трябва да изтрия всички характеристики от родител до неограничена дълбочина.. така че адаптирах вашия подход: MATCH (ch:Characteristic) WHERE (:Characteristic {id: {characteristicId}})-[:CONTAINS*]->(ch) OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)..., но в момента не изтрива никакви Characteristic.. тестът ми е неуспешен. - person alexanoid; 22.05.2017
comment
Разбрах, че идентификаторът, който имате предвид, е идентификаторът на възел neo4j, нали? Трябва да използвате функцията id, за да съпоставите този идентификатор. MATCH (rn), (ch:Characteristic) WHERE id(rn) = {characteristicId} AND (rn)-[:CONTAINS*]->(ch) OPTIONAL MATCH (ch)<-[:SET_ON]-(v:Value)-[:SET_FOR]->(Decision) OPTIONAL MATCH (v)-[:CONTAINS]->(vE) OPTIONAL MATCH (vE)-[:CONTAINS]->(vEE) OPTIONAL MATCH (ch)-[:CONTAINS]->(cho:CharacteristicOption) OPTIONAL MATCH (cho)-[:CONTAINS]->(choE) OPTIONAL MATCH (ch)-[:CONTAINS]->(chE) DETACH DELETE choE, cho, ch, vEE, vE, v, chE - person bjornbergq; 22.05.2017
comment
Освен това, ако използвате вътрешния идентификатор на neo4j, не забравяйте да го промените и никога не използвайте вътрешния идентификатор във вашето приложение. :) - person bjornbergq; 22.05.2017
comment
Благодаря. Вашата заявка работи без грешки, но тестът ми е неуспешен, защото изтрива всички характеристики с изключение на 1.. Мисля, че освен родителската характеристика.. но трябва да я обработя и изтрия също - person alexanoid; 22.05.2017
comment
Освен това има свойство в Neo4j, което не позволява на Neo4j повторно използване на вътрешно ID.. така че изглежда, че е безопасно да използвате тези идентификатори с това свойство - person alexanoid; 22.05.2017
comment
този neo4j.com /docs/operations-manual/current/reference/ - person alexanoid; 22.05.2017
comment
Може би променете [:CONTAINS*] на [:CONTAINS*0..1], за да включите основния възел. - person bjornbergq; 23.05.2017
comment
Благодаря ! изглежда, че този работи [:CONTAINS*0..] за неограничена дълбочина - person alexanoid; 23.05.2017

Предполагам, че всички потомци на Characteristic също ще имат етикета Characteristic. Друго предположение, което направих, е, че имате нужда от characteristicId, който е дефиниран от вас, а не от вътрешния идентификатор, дефиниран от neo4J. id(ch) извлича вътрешния идентификатор вместо потребителски идентификатор. Може да искате да подадете променливата characteristicId, както дадох тук.

MATCH (chparent:Characteristic {characteristicId: <someid>})
WITH chparent
OPTIONAL MATCH (chparent)-[:CONTAINS]->(chchild:Characteristic)
WITH chchild
<your operation>
person hhsecond    schedule 21.05.2017
comment
Благодаря за вашият отговор. Как да комбинирате chparent и chchild в една променлива (списък), за да не работите отделно с две различни променливи? - person alexanoid; 21.05.2017
comment
вижте apoc.coll.union за различен списък и apoc.coll.unionAllв документите. neo4j-contrib.github.io/neo4j-apoc-procedures/ - person Tomaž Bratanič; 21.05.2017