문제

다음과 같이 쿼리가 있습니다 :

MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 4 LIMIT 1 
RETURN left, right 
UNION MATCH left, right 
WHERE (ID(right) IN [1, 2, 3] AND ID(left) IN [4, 5, 6]) 
WITH left, right 
  SKIP 8 LIMIT 1 
RETURN left, right
CREATE UNIQUE left-[rel:FRIEND]->right 
RETURN rel;
.

일반적으로 나중에 고유 한 명령을 작성할 수 있도록 데이터 집합을 만드는 것입니다.


분명히 작동하지 않는 - 쿼리 분석기는 Reurn 조항을 한 번만 사용할 수 있다고합니다. 내 질문은이 경우 데이터 세트를 작성하는 방법입니다.나는 별칭을 할당하고 독창적 인 작성에 그것을 사용하려고 노력했다.내가 도대체 뭘 잘못하고있는 겁니까?이 시나리오가 가능한 시나리오입니까?

도움이 되었습니까?

해결책

나는 당신이 이후에 오해 할 수 있지만, 당신의 질의를 볼 때 나에게 일어나는 일은 여기에 있습니다.

SKIP 또는 LIMIT없이 RETURNUNION를 사용하는 쿼리의 적응이 시작됩니다.

MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right 
    LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH [rel] as rels  //If you want to return the relationship later you can put it in a collection and bring it WITH
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 4 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
MATCH left, right
WHERE ID(left) IN [1,2,3] AND ID(right) IN [4,5,6]
WITH left, right, rels 
    SKIP 8 LIMIT 1
CREATE UNIQUE left-[rel:FRIEND]->right
WITH rels + [rel] as rels
RETURN LENGTH(rels), rels  // You can return the relationships here but SKIP/LIMIT does its job also if you don't return anything
.

그러나이 쿼리는 비트 야생입니다. 정말로 세 가지 쿼리입니다. 여기서 두 개의 인위적으로 첫 번째 쿼리로 인위적으로 짜납니다. 각 하위 쿼리에서 동일한 노드와 동일한 노드와 일치하며 별도로 사용하지 않고 실제로 쿼리를 실행하여 쿼리를 실행하여 얻은 것이 아닙니다 (실제로 느려지는 것은 실제로 느려집니다. .

이므로 첫 번째 제안은 ID로 노드를 가져올 때 START 대신 MATCH...WHERE를 사용하는 것입니다. 쿼리가 데이터베이스의 모든 노드를 "왼쪽"으로 바인딩 한 다음 데이터베이스의 모든 노드를 "오른쪽"으로 바인딩 한 다음 조건에 맞지 않는 모든 노드를 "왼쪽"으로 바인드하는 모든 노드를 필터링합니다. WHERE 절을 사용한 다음 "오른쪽"에 대해 동일합니다. 쿼리 의이 부분이 세 번 반복되므로 데이터베이스의 모든 노드가 총 6 번 바인딩됩니다. 그것은 세 가지 관계를 만드는 데 비싸다. START를 사용하는 경우 즉시 원하는 노드를 바인딩 할 수 있습니다. 이것은 실제로 귀하의 질문에 대답하지는 않지만 더 빠를 것이며 쿼리는 클리너가 될 것입니다. 따라서 START를 사용하여 내부 ID로 노드를 가져옵니다.

START left = node(1,2,3), right = node(4,5,6)
.

패턴을 일치시킬 때 노드와 '경로'또는 '결과 항목'의 차이점은 생각하는 두 번째 방법입니다. "왼쪽"에 세 개의 노드를 묶어 줄 때 "오른쪽"에서 다른 세 개의 노드가 3 개의 결과 항목이 있지만 9 개가 없습니다. "왼쪽"에서 바인딩 된 각 노드에 대해 세 가지 결과가 있으므로 세 가지 결과가 있기 때문에 "오른쪽"이 있기 때문에 함께 결합 할 수 있습니다. 당신이 모든 "왼쪽"을 모든 "왼쪽"에 연관시키고 싶다면, 훌륭합니다. 그러나 당신이 찾고있는 것은 결과 항목이 (1),(4), (2),(5), (3),(6), 3 개의 "왼쪽"노드와 세 개의 "오른쪽"노드를 노드 ID의 컬렉션을 갖춘 하나의 쿼리에 하나의 쿼리에 두 개의 "오른쪽"노드를 바인딩하는 것이 편리합니다. 6 개의 원하지 않는 일치를 제거하기 위해 모든 필터링을해야합니다. 쿼리는 복잡하고 번거롭고 쿼리를 개별적으로 실행하는 것보다 실제로 느립니다. 이것을 말하는 또 다른 방법은 (1)-[:FRIEND]->(4)가 생성중인 다른 패턴에 연결된 (관련성있게) 연결되지 않은 다른 패턴이라고 말하는 것입니다. (1)-[:FRIEND]->(2)<-[:FRIEND]-(3)를 만들고 싶다면 다른 세 개의 노드를 함께 처리하려는 경우 다를 것입니다. 어쩌면 당신은 단지 cypher의 프린지 용도를 탐구하는 것입니다. 그러나 나는 그것을 지적해야한다고 생각했습니다. 그런데 SKIPLIMIT를 사용 하여이 방식으로 Bit Off 키는 패턴 일치 및 필터링을위한 것이 아닙니다. 결과가 특정 순서로 될 것이라는 보장이 없기 때문에 ORDER BY도 사용하지 않는 한 예측할 수 없습니다. 얻는 결과 항목은 어떤 결과를 지나치게 지나가는지 모릅니다. 어쨌든,이 경우, 노드를 바인딩하고 세 가지 별도의 쿼리로 관계를 만들 수있는 것이 좋습니다.

START left = node(1), right = node(4)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(2), right = node(5)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

START left = node(3), right = node(6)
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel
.

이미 세 쌍을 원한다는 것을 이미 알고 있으며, (1),(4), (1),(5), (1),(6)이 쌍만있는 쿼리를 쿼리하는 것이 좋습니다.

셋째로 은 세 가지 쿼리가 구조적으로 동일하므로 속성 값에서만 다릅니다 (ID가 속성으로 간주되는 경우) 일반화 또는 익명화를 통해 쿼리를 단순화 할 수 있습니다. 즉 매개 변수를 사용합니다.

START left = node({leftId}), right = node({rightId})
CREATE UNIQUE left-[rel:FRIEND]->right
RETURN rel

parameters: {leftId:1, rightId:4}, {leftId:2, rightId:5}, {leftId:3, rightId:6}
.

구조가 동일하기 때문에 cypher는 실행 계획을 캐시 할 수 있습니다. 이것은 좋은 성능을 제공하며 쿼리는 깔끔하고 유지 보수가 가능하며 나중에 다른 노드 쌍에 대해 동일한 작업을 수행하려는 경우 쉽게 확장 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top