5

シナリオは次のとおりです。項目を含む ArangoDB コレクションと、タグを含む別のコレクションがあります。私はグラフを使用しており、アイテムとタグを接続する「Contains」というエッジ コレクションがあります。アイテムには複数のタグがあります。

現在、複数のタグを含むアイテムを検索しようとしています。たとえば、「写真」、「ポートレート」、「顔」のタグを含むアイテム。

私の一般的なアプローチは、各タグの頂点からグラフ トラバーサルを開始し、そのタグに関連するアイテムを見つけることです。その部分はうまく機能します。アイテムのリストを取得します。

しかし、私のタスクの最後の部分は、指定されたすべてのタグを含むアイテムを見つけるために、すべてのリストの共通部分を作成することです。そして、私はこれを行う方法を理解できません。

私がやりたかったことは次のようなものでした:

let tagnames = SPLIT(@tagnames,',')
let tagcollections = (
    FOR tagname IN tagnames
    LET atag = (FOR t IN tags FILTER LOWER(t.text)==LOWER(tagname) RETURN t)
    let collections = (FOR v IN 1..1 INBOUND atag[0] Contains RETURN v)

    RETURN { tag: atag, collections: collections }
)

RETURN INTERSECTION(tagcollections)

ただし、機能しません。INTERSECTION 関数は単一のリストでは機能しませんが、次のように複数の項目で機能します: INTERSECTION(listA, listB, listC...)。

FOR .. RETURN ブロックで見つかったリストの交差を作成するにはどうすればよいですか?

4

3 に答える 3

5

ArangoDB 3.0 では、特別な配列比較演算子( ANYALLNONE) が導入されました。ALL IN左側の配列のすべての要素が右側の配列にもあるかどうかをテストするために使用できます。

[ "red", "green", "blue" ] ALL IN [ "purple", "red", "blue", "green" ]
// true

これらの演算子はまだインデックスを使用できないことに注意してください。タグをドキュメントに直接埋め込むデータ モデルの場合、回避策は、インデックスを使用して、タグの 1 つを含むすべてのドキュメントを検索し (たとえば、最初の要素 を取得["red","green","blue"][0])、完全なコレクション スキャンを行わずに結果セットを減らすことです。ALL IN他のタグもリストにある場合のポストフィルター:

LET tagsToSearchFor = [ "red", "green", "blue" ]
FOR doc IN coll
  FILTER tagsToSearchFor[0] IN doc.tags[*] // array index
  FILTER tagsToSeachFor ALL IN doc.tags
  RETURN doc

ALL INタグの別のコレクションを使用してデータ モデルに使用することもできますが、上記のようなインデックスを使用することはできません。例えば:

FOR doc IN documents
    LET tags = (
        FOR v IN INBOUND doc contains
            RETURN v._key
    )
    FILTER ["red", "green", "blue"] ALL IN tags
    RETURN MERGE(doc, {tags})

または、タグを使用してトラバーサルを開始し、交差ベースのアプローチを使用する場合:

LET startTags = ["red", "green", "blue"] // must exist
LET ids = (
    FOR startTag IN DOCUMENT("tags", startTags)
        RETURN (
            FOR v IN OUTBOUND startTag contains
                RETURN v._id
        )
)
LET docs = APPLY("INTERSECTION", ids)

FOR doc IN DOCUMENT(docs)
    RETURN MERGE(doc, {
        tags: (FOR tag IN INBOUND doc contains RETURN tag._key)

    })
于 2016-07-20T14:45:14.163 に答える
3

タグをアイテムの属性として保存することを検討します。ArangoDB 2.8 には、シナリオを正確に対象とした配列インデックスが含まれています。彼らのブログ投稿から:

{ 
  text: "Here's what I want to retrieve...",
  tags: [ "graphdb", "ArangoDB", "multi-model" ]   
}

FOR doc IN documents 
  FILTER "graphdb" IN doc.tags[*] 
    RETURN doc

これにより、パフォーマンスが向上し、上記の AQL が不要になり、アプリが簡素化されます。

于 2016-02-26T22:40:02.870 に答える