2017-05-23 14 views
1

私は以下の構造を持っています。完全パスのNeo4jクエリ

CREATE 
(`0` :Sentence {`{text`:'This is a sentence'}}) , 
(`1` :Word {`{ text`:'This' }}) , 
(`2` :Word {`{text`:'is'}}) , 
(`3` :Sentence {`{'text'`:'Sam is a dog'}}) , 
(`0`)-[:`RELATED_TO`]->(`1`), 
(`0`)-[:`RELATED_TO`]->(`2`), 
(`3`)-[:`RELATED_TO`]->(`2`) 

schema example

だから私の質問はこれです。私は単語のオブジェクトに分解した文章をたくさん持っています。これらの単語オブジェクトはすべて一意であり、したがって異なる文を指すことになる。 1つの単語の検索を実行すると、その単語が関連するすべての文を理解することが非常に簡単です。どのようにして1つではなく2つの単語について同じ情報を把握するようにクエリを構成することができますか?

私は2つ以上の単語を提出し、すべての関心のある文章を拾い上げて提出されたすべての単語を含むパスを探したいと思います。

答えて

0

残念ながら、それは非常にきれいなアプローチではありません。基本的にWordノードを収集し、ALL()述語を使用して、コレクションのすべての要素に対して正しいパターンが保持されるようにします。これは醜いになり何

MATCH (w:Word) 
WHERE w.text in {myListOfWords} 
WITH collect(w) as words 
MATCH (s:Sentence) 
WHERE ALL(word in words WHERE (s)-[:RELATED_TO]->(word)) 
RETURN s 

は、プランナーがあなたがMATCH (s:Sentence) WHERE ALL(word in words ...sの初期マッチがあなたのwordsコレクションの最初のwからの一致から来るべきことを言うときことを推測するために今十分にインテリジェントではないということですだから、すべてのものから始めます。文章のノードが最初にあります。これは、大きなパフォーマンスのヒットです。

これを回避するには、wordsコレクションの最初から明示的に一致させ、残りの部分にWHERE ALL()を使用する必要があります。

MATCH (w:Word) 
WHERE w.text in {myListOfWords} 
WITH w, size(()-[:RELATED_TO]->(w)) as rels 
WITH w ORDER BY rels ASC 
WITH collect(w) as words 
WITH head(words) as head, tail(words) as words 
MATCH (s)-[:RELATED_TO]->(head) 
WHERE ALL(word in words WHERE (s)-[:RELATED_TO]->(word)) 
RETURN s 

EDIT:

を追加しました彼らの着信の程度によって、あなたのwノードを注文するには、最適化:これは、初期の一致を意味するとして、RELATED_TO関係(これは非常に少数のノード上の度合い参照です)あなたの:文のノードは残りの単語との関係をフィルタリングする前にできるだけ小さな開始セットです。

+0

感謝。私はこのウサギの穴に向かい始めます。私はPythonとCypherを混在させているので、おそらく私は上記をいくつかの小さなクエリに分解することができます –

1

もっとうまくいくかもしれない別のアプローチを思い出しました。このクエリのPROFILEと他のプロファイルのプロファイルを比較して、効果的かどうかを確認してください。

WITH {myListOfWords} as wordList 
WITH wordList, size(wordList) as wordCnt 
MATCH (s)-[:RELATED_TO]->(w:Word) 
WHERE w.text in wordList 
WITH s, wordCnt, count(DISTINCT w) as cnt 
WHERE wordCnt = cnt 
RETURN s 
0

別の方法として、あなたの代わりにWordノードとRELATED_TO関係を使用しての(とも呼ばれる「レガシーインデックス」)manual indexingの使用を検討できます。手動索引はluceneを使用して "全文"検索をサポートします。

apoc proceduresがあります。

これはあなたの役に立つ例です。この例では、大文字と小文字を区別しない比較がOKであると仮定して、Sentenceノード(およびそれらのtextプロパティ)を保持し、すべてのSentenceノードのtextプロパティをマニュアルインデックスに自動的に追加したいとします。

  1. neo4jを使用している場合3。2+は、使用可能ないくつかの高価なapoc.index手順(のようなapoc.index.addAllNodes)を作るためにneo4j.confファイルにこの設定を追加する必要があります。

    dbms.security.procedures.unrestricted=apoc.* 
    
  2. textテキストで「WordIndex」という名前のマニュアルインデックスを初期化するために、このサイファーコードを実行します既存のすべてのSentenceノードから、以降その時点から自動索引付けを有効にする(鈍感ケース)コレクション内のすべての単語を含むSentenceノードを見つけるために

    CALL apoc.index.addAllNodes('WordIndex', {Sentence: ['text']}, {autoUpdate: true}) 
    YIELD label, property, nodeCount 
    RETURN *; 
    
  3. (PASSE dを$wordsparameter)、以下のようなCypherステートメントを実行します。 WITH句では、luceneのクエリ文字列(「foo AND bar」など)が作成されます。注意:luceneの特殊なブール値(ANDやORなど)は常に大文字であるため、渡す単語が小文字であることを確認する必要があります(または、WITH節を修正してTOLOWER() )。

    WITH REDUCE(s = $words[0], x IN $words[1..] | s + ' AND ' + x) AS q 
    CALL apoc.index.search('WordIndex', q) YIELD node 
    RETURN node; 
    
関連する問題