[neo4j] 관계가없는 경우 노드 반환

요리사가 가질 수있는 누락 된 재료를 “찾기”하는 cypher를 사용하여 쿼리를 만들려고합니다. 내 그래프는 다음과 같이 설정됩니다.

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

(ingredient)키 / 값은 name = “dye colors”입니다. (ingredient_value)key / value는 value = “red”이고 “is part of”일 수 (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가 수행 할 수있는 것입니까, 아니면 모든 재료를 반환하고 직접 분류하여 가장 잘 처리되는 것입니까?

보너스 : 또한 셰프가 가지고있는 모든 값을 레시피에 필요한 모든 값과 일치시키기 위해 cypher를 사용하는 방법이 있습니다. 지금까지 a에 의해 반환 된 모든 부분 일치 만 반환 chef-[:has_value]->ingredient_value<-[:requires_value]-recipe하고 결과를 직접 집계했습니다.



답변

2013 년 1 월 10 일 업데이트 :

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

이제 존재하지 않는 (null) 관계를 확인할 수 있습니다.


답변

관계가없는 노드를 가져 오는 경우

관계가 있는지 여부를 확인하는 좋은 옵션입니다.

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

이에 대한 여러 조건을 확인할 수도 있습니다. “played”또는 “notPlayed”관계가없는 모든 노드를 반환합니다.

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

실현성이없는 노드를 가져 오려면

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

들어오는 / 나가는 관계가없는 노드를 확인합니다.


답변

“조건부 제외”의미 체계가 필요한 경우이 방법을 사용할 수 있습니다.

neo4j 2.2.1부터 OPTIONAL MATCH절 을 사용 하여 일치하지 않는 ( NULL) 노드를 필터링 할 수 있습니다 .

사용하는 것도 중요하다 WITH사이 절 OPTIONAL MATCHWHERE, 절을 그래서 먼저 WHERE정의하는 옵션 일치 조건과 두 번째 WHERE필터처럼 동작합니다.

두 가지 유형의 노드가 있다고 가정합니다. PersonCommunication. 전화로 통신 한 적이 없지만 다른 방식으로 통신했을 수있는 모든 사람을 얻으려면 다음 쿼리를 작성합니다.

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

경기 패턴은 통신을 가진 모든 사람과 일치합니다 cNULL이외의 전화 통신을합니다. 그런 다음 필터 ( WHEREWITH)는 다른 모든 전화 통신을 필터링합니다.

참조 :

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


답변

Cypher 2.0을 사용하여 이것이 어떻게 자연스럽게 이루어질 수 있는지 보여주는 요점을 작성했습니다.

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

요점은 사용 가능한 재료에 대한 선택적 일치를 사용한 다음 누락 된 (null) 재료 또는 잘못된 값을 가진 재료를 필터링하기 위해 비교하는 것입니다.

개념은 선언적이며 알고리즘을 설명 할 필요가 없으며 필요한 것을 적어두면됩니다.


답변

나는 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 버전에서는 이것을 사이퍼 언어로 공식화 할 수 없었다.


답변

마지막 쿼리는 다음과 같아야합니다.

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관계의 길이가 0이어야 함을 의미합니다. 즉, 재료와 요리사는 동일한 노드 여야하지만 그렇지 않습니다.


답변