İlişki yoksa düğümü döndür


90

Cypher kullanarak bir şefin sahip olabileceği eksik malzemeleri "bulacak" bir sorgu oluşturmaya çalışıyorum. Grafiğim şöyle ayarlandı:

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

(ingredient)name = "dye colors" anahtar / değerine sahip olacaktır. (ingredient_value)değerin bir anahtarı / değeri olabilir = "kırmızı" ve " (ingredient, name="dye colors").

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

Bu sorguyu ingredients, bir tarifin gerektirdiği, ancak gerçek değerlerini almak için kullanıyorum , ancak ingredientsher tarifin gerektirdiği tüm malzemeler yerine yalnızca şefin sahip olmadığı geri dönüşü istiyorum . denedim

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

ama bu hiçbir şey döndürmedi.

Bu, cypher / neo4j ile başarılabilecek bir şey mi yoksa bu, en iyi şekilde tüm malzemeleri iade edip bunları kendim sıralayarak ele alınabilecek bir şey mi?

Bonus: Ayrıca, bir şefin sahip olduğu tüm değerleri bir tarifin gerektirdiği tüm değerlerle eşleştirmek için cypher'ı kullanmanın bir yolu var. Şimdiye kadar sadece a tarafından döndürülen chef-[:has_value]->ingredient_value<-[:requires_value]-recipeve sonuçları kendim toplayan tüm kısmi eşleşmeleri geri verdim.


V3 ile ilgili bilgiler için burayı kontrol edin: stackoverflow.com/questions/25673223/…
Maciej

Gelecekteki kullanıcılar için; daha fazla bilgi için neo4j.com/developer/subqueries/#existential-subqueriesexists bir WHEREcümlecikte kullanabilir (aynı zamanda onu reddedebilirsiniz ) .
ozanmuyes

Yanıtlar:


159

Güncelleme 01/10/2013:

Neo4j 2.0'da bununla karşılaştım referansında :

İsteğe bağlı ilişkileri kullanmamaya çalışın. Her şeyden önce,

onları böyle kullanma:

MATCH a-[r?:LOVES]->() WHERE r IS NULL Var olmadıklarından emin olun.

Bunun yerine bunu şu şekilde yapın:

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

İlişkinin var olup olmadığını kontrol etmek için şifreyi kullanma:

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

? işareti, ilişkiyi isteğe bağlı hale getirir.

VEYA

Neo4j 2'de şunları yapın:

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

Artık mevcut olmayan (boş) ilişkiyi kontrol edebilirsiniz.


3
Neo4j 2.0, kullanımı isteğe eşleşme, kelimenin ilk örnek, isteğe bağlı MATCH (kaynak) gibi görünür, yani isteğe bağlı ilişkileri eşleştirmek için - [r: someType] - (hedef) GERİ kaynağı, r
durgunluk

NEREDE DEĞİL içinde etiketli bir düğüme sahip olmaya çalışıyorum, çalışmıyor. Gibi: (a) OLMAYAN BİR YERDE EŞLEŞTİRİN - [: SEVİYOR] -> (Yabancı), bu 'Yabancı' bir düğüm etiketidir. Neo4j 2.1.2 sürümünü kullanıyorum
Krishna Shetty

1
Boşver, bu cevaba ulaşmak için ilerlemeyi neden göstermek istediğini anlıyorum: (a) - [: SEVİYOR] -> ()
NumenorForLife

4
MATCH a...Örnek şimdi olmalıMATCH (a) WHERE NOT (a)-[:LOVES]->()
Liam

1
@ gil-stal Bu sorgu ile düğüm adını neden böyle kullanamıyorum. (A) OLMAYAN BİR YERDE EŞLEŞTİRİN - [: SEVİYOR] -> (b: Bir Etiket). Düğüm adını kullanmazsam işe yarıyor.
iit2011081

16

Herhangi bir ilişkisi olmayan düğümleri getirmek için

Bu, ilişkinin var olup olmadığını kontrol etmek için iyi bir seçenektir.

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

Bunun için birden fazla koşulu da kontrol edebilirsiniz. İlişki "oynatılmayan" veya "oynatılmayan" tüm düğümleri döndürür.

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

Herhangi bir ilişkisi olmayan düğümleri getirmek için

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

Herhangi bir gelen / giden ilişkisi olmayan düğümü kontrol edecektir.


4
MATCH (player) WHERE NOT (player)-[r]-() RETURN playerDeğişken r tanımlanmadı hatası verir . R'yi nasıl tanımlayabilirim?
Chathura Wijeweera

bunu düzeltmek için ya bir ilişki belirtin (örneğin (player -[:rel]- ()) ya da herhangi bir ilişki için boş bırakın(player -[]- ()
Archemar

MATCH (player) WHERE NOT (player)-[]-() RETURN player- İyi çalışıyor
Prashanth Terala

İlk sorgunuz aslında yanlış. MATCH modelinin kendisi her zaman yalnızca mevcut ilişkileri döndürür, hiçbiri NULL olmaz. Yani WHERE satırınızın filtrelenecek hiçbir şeyi yok.
Cristi S.

@CristiS. Bana bildirdiğiniz için teşekkürler. Çalışması gereken sorguyu güncelledim
Satish Shinde

8

"Koşullu dışlama" anlamsallığına ihtiyacınız varsa, bu şekilde başarabilirsiniz.

Neo4j 2.2.1'den itibaren, OPTIONAL MATCHcümle kullanabilir ve eşleşmeyen ( NULL) düğümleri filtreleyebilirsiniz .

Ayrıca ve cümleleri WITHarasında cümle kullanmak da önemlidir , böylece ilki isteğe bağlı eşleşme için bir koşul tanımlar ve ikincisi bir filtre gibi davranır.OPTIONAL MATCHWHEREWHEREWHERE

2 tür düğümümüz olduğunu varsayarsak: Personve Communication. Hiç telefonla iletişim kurmamış, ancak başka yollarla iletişim kurmuş olabilecek tüm Kişileri almak istersem, şu soruyu yapardım:

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

Maç modeli, tüm Kişilerle telefon dışı İletişimlerin colacağı iletişimleri ile eşleşecektir NULL. Sonra filtre ( WHEREsonraWITH ) diğer tüm telefon iletişimlerini bırakarak filtreleyecektir.

Referanslar:

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


2

Bunun Cypher 2.0 kullanılarak oldukça doğal bir şekilde nasıl yapılabileceğini gösteren bir özet yazdım.

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

Kilit nokta, mevcut bileşenlerle isteğe bağlı eşleştirme kullanmak ve ardından eksik (boş) bileşenleri veya yanlış değere sahip bileşenleri filtrelemek için karşılaştırmaktır.

Kavramın açıklayıcı olduğunu ve bir algoritmayı tanımlaması gerekmediğini unutmayın, sadece ihtiyacınız olanı yazın.


2

Bu görevi gremlin kullanarak tamamladım. yaptım

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()

Bu, tüm eksik bileşenlerin yollarını döndürdü. Bunu cypher dilinde formüle edemedim, en azından sürüm 1.7 için.


2

Son sorgu şu şekilde olmalıdır:

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

Bu desen: (ingredient)<-[:has_ingredient*0..0]-chef

Hiçbir şey iade etmemesinin nedeni budur. *0..0ilişkilerin uzunluğunun sıfır olması gerektiği anlamına gelir, bu da bileşen ve şefin aynı düğüm olması gerektiği anlamına gelir;


Evet, ancak istenen malzemeyi geri vermiyor. Şefin tarifle zaten ortak olan şeyleri geri getiriyor, farkı bulmak istiyorum.
Nicholas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.