2016-09-18 9 views
0

与えられたモデルNeo4jのcypherクエリ(UNIONの代わり)を組み合わせる最も良い方法は?

モデル間にはカテゴリと関係があります。 リレーションの場合、特定の開始カテゴリまたは終了カテゴリにバインドされている場合は、リレーションを指定できます。

  • のみ開始カテゴリが指定されている(例:「送信」)
  • のみエンドカテゴリが指定されている(例:「受信」)
  • ザ・は関係の4種類があります

  • 両方、開始および終了カテゴリが指定されている(例:「発信と着信」)
  • どちらない開始も終了カテゴリが指定されている(例:「未結合」)

コード:あなたが関係し、得られエンドノードを作成することができ、開始ノードとして「猫」を選択し、お知りになりたい場合は

MERGE (cat:ModelCategory {title:'Cat'}) 
MERGE (rel1:ModelRelation {title:'Outgoing'}) 
MERGE (rel2:ModelRelation {title:'Incoming'}) 
MERGE (rel3:ModelRelation {title:'Outgoing and Incoming'}) 
MERGE (rel4:ModelRelation {title:'Unbound'}) 
MERGE (rel1)-[:STARTS_AT]->(cat) 
MERGE (rel2)-[:ENDS_AT]->(cat) 
MERGE (rel3)-[:STARTS_AT]->(cat) 
MERGE (rel3)-[:ENDS_AT]->(cat) 

Neo4j Browser Screenshot

シングルはあなたができる、

を問い合わせます単一のクエリを使用します。

// Relations with current source and a target 
// Returns relation "Outgoing and Incoming" 
MATCH (relation:ModelRelation)-[STARTS_AT]->(:ModelCategory{title:"Cat"}), 
(relation)-[ENDS_AT]->(target) 
RETURN DISTINCT relation, target 

// Relations with current source and without target 
// Returns relation "Outgoing" 
MATCH (relation:ModelRelation)-[STARTS_AT]->(:ModelCategory{title:"Cat"}) 
WHERE NOT (relation)-[:ENDS_AT]->() 
MATCH (allCategories:ModelCategory) 
RETURN relation, allCategories as target 

// Relations with target, without source 
// Returns relation "Incoming" 
MATCH (relation:ModelRelation)-[ENDS_AT]->(target) 
WHERE NOT (relation)-[:STARTS_AT]->() 
RETURN relation, target 

// Relations without source or target 
// Returns relation "Unbound" 
MATCH (relation:ModelRelation) 
WHERE NOT (relation)-[:STARTS_AT]->() AND NOT (relation)-[:ENDS_AT]->() 
MATCH (allCategories:ModelCategory) 
RETURN relation, allCategories as target 

質問を

4つのクエリを組み合わせる最も良い方法は何ですか?
最も簡単な解決策は、ステートメントの間にUNIONを追加することです。
ラベルModelRelationとModelCategoryのすべてのノードを最初に取得し、サブグラフでさらにクエリを実行することをお勧めしますか?

更新

より良い解決策は、指定されたターゲットの有無にかかわらず関係の間disginguishすることです。 (1つのカテゴリまたはすべてのカテゴリで発生します).1つのUNIONはまだ必要であり、両方のサブクエリの最初の部分は同じです。

// Relations which start at selected category or have no specified start 
MATCH (relation:ModelRelation) 
WHERE (relation)-[:STARTS_AT]->(:ModelCategory{title:"Cat"}) OR 
     NOT (relation)-[:STARTS_AT]->() 

// Relations with specified targets 
Match (relation)-[ENDS_AT]->(target) 
RETURN relation, target 

UNION 

// Relations which start at selected category or have no specified start 
MATCH (relation:ModelRelation) 
WHERE (relation)-[:STARTS_AT]->(:ModelCategory{title:"Cat"}) OR 
     NOT (relation)-[:STARTS_AT]->() 

// Relations without specified targets 
MATCH (relation) 
WHERE NOT (relation)-[:ENDS_AT]->() 
MATCH (allCategories:ModelCategory) 
RETURN relation, allCategories as target 

答えて

1

用フィルター表記と可変長パスは、次にallCategoriesでNULL値を置き換えるためにCASE文を使用し、あるクエリでこのすべてをキャッチします。

MATCH (m:ModelCategory) 
WITH COLLECT(m) AS allCategories 
MATCH path = (:ModelCategory) <- [:STARTS_AT*0..1] - (:ModelRelation) - [:ENDS_AT*0..1] -> (:ModelCategory) 
WITH CASE WHEN ANY(x in RELATIONSHIPS(path) WHERE TYPE(x) = 'STARTS_AT') THEN NODES(path)[0] ELSE allCategories END AS start, 
[x IN NODES(path) WHERE x:ModelRelation][0] as relation, 
CASE WHEN ANY(x IN RELATIONSHIPS(path) WHERE TYPE(x) = 'ENDS_AT') THEN LAST(NODES(path)) ELSE allCategories END AS end 
RETURN start, relation, end 

一般的に、あなたは常にUNIONCOLLECTの適切な組み合わせを使用してクエリ、CASE、およびいずれかOPTIONAL MATCHまたは長さ0のパスを置き換えることができます。すべてのクエリで同じ列のレイアウトを返すのではなく、結果に対して集計を実行できるので、歪みを処理する価値があります。

EDIT:リレーションごとに単一の行を返す単純なバージョンです。

MATCH (m:ModelCategory) 
WITH COLLECT(m) AS allCategories 
MATCH (relation:ModelRelation) 
OPTIONAL MATCH (relation) - [:STARTS_AT] -> (start:ModelCategory) 
OPTIONAL MATCH (relation) - [:ENDS_AT] -> (end:ModelCategory) 
WITH COLLECT(start) AS starts, relation, COLLECT(end) AS ends, allCategories 
RETURN 
CASE starts WHEN [] THEN allCategories ELSE starts END AS relationStarts, 
relation, 
CASE ends WHEN [] THEN allCategories ELSE ends END AS relationEnds 
関連する問題