2017-08-14 1 views
0

私の直感は答えはノーですが、順序が重要な配列の類似性を比較してMongodbで検索することは可能ですか?配列の優先順位で検索する

など。 それは私が検索を行うと理想的には1

と同じ値のすべてが含まれていますので、

{'_id':1, "my_list": ["A",2,6,8,34,90]}, 
{'_id':2, "my_list": ["A","F",2,6,19,8,90,55]}, 
{'_id':3, "my_list": [90,34,8,6,3,"A"]} 

1及び2は、最も類似しているように私には、3つの文書を持っている3は関係なく、実際の乱暴に異なっています{"my_list" : ["A",2,6,8,34,90] }に似ており、結果は文書1と2になります。

これはワイルドカードを使った正規表現検索とほとんど同じです。私はPythonでこれを簡単に十分に行うことができると知っていますが、速度は重要で、私は130万の文書を扱っています。

+0

「比較する」とはどういう意味ですか?コレクション内の各ドキュメントを他のすべてのドキュメントと比較したいですか?または、代わりに、提供された配列をドキュメントに実際に格納されている配列と比較するように求めていますか?これらのアプローチは大きく異なりますので、実際にどのようなことを求めているかについては明確にする必要があります。 –

+0

私はこの問題を修正しました。配列を提供していて、同様の配列を含むドキュメントをコレクションで検索しています。 – danspants

+0

すべてのdocumnetsを繰り返し、コードでいくつかのロジックを使用して、mongoはこれらの種類のロジックにプロビジョニングされません。あなたはこれのためにアルゴをデザインする必要があります。 –

答えて

0

「比較」または「選択」は、実際に適用される論理に実際には多少なりとも主観的です。しかし、一般的な原則として、配列と一致するインデックスの積と、ドキュメント内に存在する配列を常に検討することができます。例えば:

var sample = ["A",2,6,8,34,90]; 

db.getCollection('source').aggregate([ 
    { "$match": { "my_list": { "$in": sample } } }, 
    { "$addFields": { 
    "score": { 
     "$add": [ 
     { "$cond": { 
      "if": { 
      "$eq": [ 
       { "$size": { "$setIntersection": [ "$my_list", sample ] }}, 
       { "$size": { "$literal": sample } } 
      ] 
      }, 
      "then": 100, 
      "else": 0 
     }}, 
     { "$sum": { 
      "$map": { 
      "input": "$my_list", 
      "as": "ml", 
      "in": { 
       "$multiply": [ 
       { "$indexOfArray": [ 
        { "$reverseArray": "$my_list" }, 
        "$$ml" 
       ]}, 
       { "$indexOfArray": [ 
        { "$reverseArray": { "$literal": sample } }, 
        "$$ml" 
       ]} 
       ] 
      } 
      } 
     }} 
     ] 
    } 
    }}, 
    { "$sort": { "score": -1 } } 
]) 

このような順序で文書を返す:

/* 1 */ 
{ 
    "_id" : 1.0, 
    "my_list" : [ "A", 2, 6, 8, 34, 90], 
    "score" : 155.0 
} 

/* 2 */ 
{ 
    "_id" : 2.0, 
    "my_list" : ["A", "F", 2, 6, 19, 8, 90, 55], 
    "score" : 62.0 
} 

/* 3 */ 
{ 
    "_id" : 3.0, 
    "my_list" : [ 90, 34, 8, 6, 3, "A"], 
    "score" : 15.0 
} 

キー$reverseArrayを使用して適用される場合、$indexOfArrayから値となること「大きい」に一致するインデックスによって生成されます「最初から最後まで」の順序(逆順)で配列の先頭のマッチに大きな重みを与えます。

もちろん、2番目の文書には実際に一致の「ほとんど」が含まれていて、最初の文書よりも最初の一致で「より大きい」重さを配置する配列のエントリが増えることを考慮する必要があります。

"A"は最初の位置に一致したにもかかわらず配列がより長いため、2番目の文書では最初のものよりもスコアが高くなります。しかし、"F"がミスマッチであるため、それが後でアレイ内にある場合よりも大きな悪影響を及ぼすという効果もあります。最後の文書の"A"にも同じことが適用されます。ここでは、配列の最後に一致が全体の重量にほとんど影響しません。

これに対処するには、サンプルの$setIntersectionと現在の配列との比較$sizeなど、「完全一致」の場合を考慮するロジックを追加することです。これはスコアを調整して、提供されたすべての要素にマッチしたものが、より少ない位置一致を有する文書よりも高いスコアを実際に獲得するようにする。

「スコア」を使用すると、実際の結果を返すために結果(つまり$limit)やその他のロジックを除外することができます。しかし、最初のステップは、作業する「スコア」を計算することです。

は、だから、実際には「最も近いマッチを」何を意味するのかロジックにすべての一般的主観ですが、$reverseArray$indexOfArray操作は、以前のインデックスに「より多くの重量」を置くと、一般的に鍵となる最後のではなく、一致しました。

全体として、ロジックの「計算」を探しています。集約フレームワークには利用可能な演算子がいくつかありますが、実際に適用する演算子は最終実装までです。私は、 "後者のマッチ"よりも配列の比較において、 "以前のマッチ"に "論理的にはたらく"が、しかし実際には配列が実際に同じである "最も重要な"ものを示しています。

:同様のロジックは、上記使用される主要な演算子なしのMongoDBの以前のバージョンの$unwindincludeArrayIndexオプションを使用して達成することができます。しかし、最初にアレイを分解するためには、このプロセスでは$unwindの使用が必要です。この場合、パフォーマンスが低下するため、操作の有効性が無効になる可能性があります。

関連する問題