副問合せを使用してユニークな作業を作成する方法
質問
このようなクエリを持っています:
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;
.
一般的に、データセットを作成するだけで、後でユニークな命令を作成することができます。
明らかに、それはうまくいかない - クエリアナライザは私がRENTING句を1回使用できることを言う。
私の質問は、この場合のデータセットを作成する方法?エイリアスを割り当て、それをCreate Uniqueで使用しようとしました - も機能することができません。私は何が悪いのですか?このシナリオは可能な限り可能な限り?
解決
私はあなたが後に何であるか誤解しているかもしれませんが、私があなたの照会を見るときに私に起こるものです。
はじめに、SKIP
またはLIMIT
なしでRETURN
とUNION
を使用するクエリの適応です。
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
.
しかし、このクエリは少し野生です。それは本当に3つのクエリです。ここで、2つは最初のサブクエリとして人工的に絞っています。それは各サブクエリで同じノードと一致します、そして、別途上にむしろこのようにクエリを実行することによって得られるものは、(実際には遅く、あなたが知っているノードも使用しないノードにも遅いため) 。
だから私の最初の提案は、IDによってノードを取得するときにSTART
の代わりにMATCH...WHERE
を使用することです。それが表すと、クエリはデータベース内のすべてのノードを「左」、次にデータベース内のすべてのノードを「正しい」とバインドし、次に「左」に設定されているすべてのノードをフィルタ解除してください。 WHERE
句、そして「右」の場合は同じです。クエリのこの部分は3回繰り返されるので、データベース内のすべてのノードは合計6回バインドされます。それは3つの関係を作成するのに高価です。 START
を使用すると、すぐに必要なノードをバインドできます。これは本当にあなたの質問に答えませんが、それはより速くなり、クエリはクリーナーになります。したがって、START
を使用して、内部IDでノードを取得します。
START left = node(1,2,3), right = node(4,5,6)
.
2番目のことは、パターンと一致するときのノードと「パス」または「結果項目」の違いです。 「左」に3つのノードをバインドすると、「右」に他の3つのノードにバインドすると、結果が3つありますが、9。 「左」にバインドされている各ノードの場合、それを組み合わせる可能性のある「右」があるため、3つの結果が得られます。あなたがすべての「左」にすべての「右」に関連したいのなら、素晴らしいです。しかし、私はあなたが探しているものは結果の項目(1),(4)
、(2),(5)
、(3),(6)
です。 6つの不要な試合を取り除くためにフィルタリングをすべて行わなければなりません。クエリは複雑で面倒なもので、クエリを別々に実行するよりも遅くなります。これを言うもう1つの方法は、(1)-[:FRIEND]->(4)
が作成している他のパターンに接続されていない(関連的に)異なるパターンであると言うことです。 (1)-[:FRIEND]->(2)<-[:FRIEND]-(3)
を作成したい場合は異なる場合があります。その3つのノードを一緒に処理したいと思うでしょう。たぶんあなたはCypherのフリンジの使用を模索しているだけですが、私はそれを指摘するべきだと思いました。ちなみに、このようにしてSKIP
とLIMIT
を使用することは少しオフのキーであり、それらは実際にはパターンマッチングとフィルタリングを目的としていません。結果が一定の順序であることが保証されていないので、一般的にはORDER BY
を使用しない限り、予測不可能です。どの結果があるかわかりません。とにかく、この場合は、ノードをバインドして3つの別々のクエリで関係を作成するのが良いと思います。
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
.
あなたはすでにあなたがこれらの3つのペアを望んでいて、(1),(4)
、(1),(5)
、(1),(6)
、それがそれらのペアのために照会することを意味します、そして最も簡単な方法は別々に照会することです。
しかし 3番目のクエリは構造的に同一であるため、プロパティ値が同じではなく(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は実行計画をキャッシュできます。これにより、優れたパフォーマンスが得られ、クエリはTIDY、MECUINTAMABE、後で他のノードのペアで同じ操作をしたい場合は簡単に拡張できます。