ส่งคืนโหนดหากไม่มีความสัมพันธ์


90

ฉันกำลังพยายามสร้างข้อความค้นหาโดยใช้ไซเฟอร์ซึ่งจะ "ค้นหา" ส่วนผสมที่ขาดหายไปที่เชฟอาจมีกราฟของฉันถูกตั้งค่าดังนี้:

(ingredient_value)-[:is_part_of]->(ingredient)

(ingredient)จะมีคีย์ / ค่าของชื่อ = "สีย้อม" (ingredient_value)อาจมีคีย์ / ค่าของ value = "สีแดง" และ (ingredient, name="dye colors")"เป็นส่วนหนึ่งของ"

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)

ฉันใช้แบบสอบถามนี้เพื่อรับingredientsค่าจริงทั้งหมดที่สูตรต้องการ แต่ฉันต้องการส่งคืนเฉพาะingredientsที่เชฟไม่มีแทนส่วนผสมทั้งหมดที่แต่ละสูตรต้องการ ฉันเหนื่อย

(chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)<-[:has_ingredient*0..0]-chef

แต่สิ่งนี้กลับไม่มีอะไรเลย

นี่คือสิ่งที่ cypher / neo4j สามารถทำได้หรือนี่คือสิ่งที่จัดการได้ดีที่สุดโดยส่งคืนส่วนผสมทั้งหมดและจัดเรียงด้วยตัวเอง?

โบนัส: นอกจากนี้ยังมีวิธีใช้ไซเฟอร์เพื่อจับคู่ค่าทั้งหมดที่เชฟมีกับค่าทั้งหมดที่สูตรต้องการ จนถึงตอนนี้ฉันได้ส่งคืนการแข่งขันบางส่วนเท่านั้นที่ส่งคืนโดย a chef-[:has_value]->ingredient_value<-[:requires_value]-recipeและรวบรวมผลลัพธ์ด้วยตัวเอง


ตรวจสอบข้อมูลที่เกี่ยวข้องกับ v3 ได้ที่นี่: stackoverflow.com/questions/25673223/…
Maciej

สำหรับผู้ใช้ในอนาคต สามารถใช้existsในWHEREประโยค (ลบล้างได้เช่นกัน), neo4j.com/developer/subqueries/#existential-subqueriesสำหรับข้อมูลเพิ่มเติม
ozanmuyes

คำตอบ:


159

อัพเดท 01/10/2556:

พบสิ่งนี้ในการอ้างอิงNeo4j 2.0 :

พยายามอย่าใช้ความสัมพันธ์ที่เป็นทางเลือก เหนือสิ่งอื่นใด,

อย่าใช้พวกเขาเช่นนี้:

MATCH a-[r?:LOVES]->() WHERE r IS NULL ที่ที่คุณตรวจสอบให้แน่ใจว่าไม่มีอยู่จริง

ให้ทำเช่นนี้แทน:

MATCH a WHERE NOT (a)-[:LOVES]->()

ใช้ cypher เพื่อตรวจสอบว่าความสัมพันธ์ไม่มีอยู่จริง:

...
MATCH source-[r?:someType]-target
WHERE r is null
RETURN source

เดอะ? เครื่องหมายทำให้ความสัมพันธ์เป็นทางเลือก

หรือ

ใน neo4j 2 ทำ:

...
OPTIONAL MATCH source-[r:someType]-target
WHERE r is null
RETURN source

ตอนนี้คุณสามารถตรวจสอบความสัมพันธ์ที่ไม่มีอยู่ (ว่าง)


3
ใน Neo4j 2.0 ให้ใช้ OPTIONAL MATCH เพื่อจับคู่ความสัมพันธ์ที่เป็นทางเลือกกล่าวคือตัวอย่างแรกจะมีลักษณะเป็น OPTIONAL MATCH (ที่มา) - [r: someType] - (เป้าหมาย) ที่มา RETURN, r
boggle

ฉันกำลังพยายามที่จะมีโหนดที่มีป้ายกำกับในที่ไหนก็ไม่ได้ผล เช่น: MATCH a WHERE NOT (a) - [: LOVES] -> (Stranger) ใน 'Stranger' คือป้ายชื่อโหนด ฉันใช้ neo4j เวอร์ชัน 2.1.2
Krishna Shetty

1
ไม่เป็นไรฉันเข้าใจว่าทำไมคุณถึงต้องการแสดงความก้าวหน้าเพื่อให้บรรลุคำตอบนี้: MATCH a WHERE NOT (a) - [: LOVES] -> ()
NumenorForLife

4
MATCH a...ตัวอย่างเช่นในขณะนี้ควรจะเป็นMATCH (a) WHERE NOT (a)-[:LOVES]->()
เลียม

1
@ gil-stal ทำไมฉันไม่สามารถใช้ชื่อโหนดกับคำค้นหานี้ได้ ตรงกับที่ที่ไม่ (a) - [: LOVES] -> (b: SomeLabel) ถ้าฉันไม่ใช้ชื่อโหนดมันก็ใช้ได้
iit2011081

16

สำหรับการดึงโหนดที่ไม่มีความสัมพันธ์ใด ๆ

นี่เป็นตัวเลือกที่ดีในการตรวจสอบความสัมพันธ์ว่ามีอยู่จริงหรือไม่

MATCH (player)
    WHERE NOT(player)-[:played]->()
    RETURN player

นอกจากนี้คุณยังสามารถตรวจสอบเงื่อนไขต่างๆได้อีกด้วยมันจะส่งคืนโหนดทั้งหมดซึ่งไม่มีความสัมพันธ์แบบ "เล่น" หรือ "ไม่เล่น"

MATCH (player) 
 WHERE NOT (player)-[:played|notPlayed]->()
 RETURN player

เพื่อดึงโหนดที่ไม่มีความเป็นจริงใด ๆ

MATCH (player) 
WHERE NOT (player)-[r]-()
RETURN player

จะตรวจสอบโหนดที่ไม่มีความสัมพันธ์ขาเข้า / ขาออก


4
MATCH (player) WHERE NOT (player)-[r]-() RETURN player ให้Variable r ไม่ได้กำหนดข้อผิดพลาด ฉันจะกำหนด r ได้อย่างไร?
Chathura Wijeweera

ในการแก้ไขปัญหานี้ให้ระบุความสัมพันธ์ (เช่น(player -[:rel]- ()) หรือเว้นว่างไว้สำหรับความสัมพันธ์ใด ๆ(player -[]- ()
Archemar

MATCH (player) WHERE NOT (player)-[]-() RETURN player- ใช้งานได้ดี
Prashanth Terala

คำถามแรกของคุณผิดจริง รูปแบบการจับคู่จะส่งคืนเฉพาะความสัมพันธ์ที่มีอยู่เสมอโดยไม่มีรูปแบบใดเป็นโมฆะ ดังนั้น WHERE ของคุณจึงไม่มีอะไรให้กรอง
Cristi S.

@ คริสตี้. ขอบคุณสำหรับการให้ฉันรู้ว่า. ฉันได้อัปเดตคำค้นหาแล้วมันควรจะใช้งานได้
Satish Shinde

8

หากคุณต้องการความหมาย "ไม่รวมตามเงื่อนไข" คุณสามารถทำได้ด้วยวิธีนี้

ใน neo4j 2.2.1 คุณสามารถใช้OPTIONAL MATCHclause และกรองNULLโหนดที่ไม่ตรงกัน ( ) ได้

สิ่งสำคัญคือต้องใช้WITHอนุประโยคระหว่างOPTIONAL MATCHและWHEREอนุประโยคเพื่อให้ข้อแรกWHEREกำหนดเงื่อนไขสำหรับการจับคู่ที่เป็นทางเลือกและข้อที่สองWHEREจะทำงานเหมือนตัวกรอง

สมมติว่าเรามีโหนด 2 ประเภท: PersonและCommunication. หากฉันต้องการรับบุคคลทั้งหมดที่ไม่เคยติดต่อทางโทรศัพท์ แต่อาจมีการสื่อสารด้วยวิธีอื่นฉันจะทำแบบสอบถามนี้:

MATCH (p: Person) 
OPTIONAL MATCH p--(c: Communication) 
WHERE c.way = 'telephone'
WITH p, c 
WHERE c IS NULL 
RETURN p

รูปแบบการจับคู่จะตรงกับบุคคลทั้งหมดที่มีการสื่อสารซึ่งcจะใช้NULLสำหรับการสื่อสารที่ไม่ใช่โทรศัพท์ จากนั้นตัวกรอง ( WHEREหลังWITH) จะกรองการสื่อสารทางโทรศัพท์ออกจากระบบอื่น ๆ ทั้งหมด

อ้างอิง:

http://neo4j.com/docs/stable/query-optional-match.html#_introduction_3 http://java.dzone.com/articles/new-neo4j-optional


2

ฉันเขียนสาระสำคัญที่แสดงให้เห็นว่าสิ่งนี้สามารถทำได้อย่างเป็นธรรมชาติโดยใช้ Cypher 2.0

http://gist.neo4j.org/?9171581

ประเด็นสำคัญคือการใช้การจับคู่ที่เป็นทางเลือกกับส่วนผสมที่มีแล้วเปรียบเทียบเพื่อกรองส่วนผสมที่ขาดหายไปหรือส่วนผสมที่มีค่าไม่ถูกต้อง

โปรดทราบว่าแนวคิดนี้มีการเปิดเผยและไม่จำเป็นต้องอธิบายอัลกอริทึมคุณเพียงแค่จดสิ่งที่คุณต้องการ


2

ฉันทำงานนี้ให้เสร็จโดยใช้ gremlin ฉันทำ

x=[]

g.idx('Chef')[[name:'chef1']].as('chef')
.out('has_ingredient').as('alreadyHas').aggregate(x).back('chef')
.out('has_value').as('values')
.in('requires_value').as('recipes')
.out('requires_ingredient').as('ingredients').except(x).path()

สิ่งนี้ส่งคืนเส้นทางของส่วนผสมที่ขาดหายไปทั้งหมด ฉันไม่สามารถกำหนดสิ่งนี้ในภาษาไซเฟอร์ได้อย่างน้อยสำหรับเวอร์ชัน 1.7


2

คำถามสุดท้ายควรเป็น:

START chef = node(..)
MATCH (chef)-[:has_value]->(ingredient_value)<-[:requires_value]-(recipe)-[:requires_ingredient]->(ingredient)
WHERE (ingredient)<-[:has_ingredient]-chef
RETURN ingredient

รูปแบบนี้: (ingredient)<-[:has_ingredient*0..0]-chef

เป็นเหตุผลที่มันไม่ได้คืนอะไรเลย *0..0หมายความว่าความยาวของความสัมพันธ์ต้องเป็นศูนย์ซึ่งหมายความว่าส่วนผสมและพ่อครัวต้องเป็นโหนดเดียวกันซึ่งไม่ใช่


ใช่ แต่จะไม่คืนส่วนผสมที่ต้องการ ส่งคืนสิ่งที่พ่อครัวมีอยู่แล้วเหมือนกันกับสูตรอาหารฉันต้องการค้นหาความแตกต่าง
Nicholas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.