2017-06-28 4 views
1

新しい$lookuppipeline機能がMongoDb 3.5.8で利用可能で、親文書のフィールドをpipelineから参照する方法が不思議でした。

親文書の2つのフィールドを、検索した文書の2つのフィールドと比較しようとしました。これを行う方法がわからない{$eq : ['$input_doc.field1', '$field1'] }

db.input_doc.aggregate([ 
     { 
      $lookup: 
      { 
       from: "foreign_doc", 
       pipeline: [ 
          { $project: { 'matched': { $and : [ 
           { $eq : ["$input_doc.field1", "$field1"] }, 
           { $eq : ["$input_doc.field2", "$field2"] } 
              ]} }, 
          { $match : { 'matched' : true } } 
       ], 
       as: "as_doc" 
      } 
     } 
    ]) 

おかげ

+0

'パイプライン'は、「非関連データ」を検索するためのものです。リレーショナルフィールドがある場合は、代わりに 'localField'と' foreignField'を使います。もちろん、データのすべての結果を論理的に比較したい場合は、配列を比較して "$ lookup"演算で配列を作成します。関連する結合にはこれを使用しないでください。 [DOCS-10298](https://jira.mongodb.org/browse/DOCS-10298)を参照してください。 –

+0

@Neil Lunn情報をありがとう。私はここに記載されているように、ローカルと外国の文書の間で複数のフィールドで参加しようとしています[SERVER-21913](https://jira.mongodb.org/browse/SERVER-21913) –

+0

チケットに記載されているとおり、オープンで未解決です、まだ機能はありません。ここでは 'foreignKey'を使って簡単に' $ lookup'をしたいようです。質問を編集して、ローカル文書と外国語文書の両方で結果として期待していることを示します。私がここで望むと思うことをするための他の方法があります。しかし、明確にするためにその事例を示してください。 –

答えて

1

それはあなたがここで何を意味するか、あなたはおそらく新しいpipelineオプションでletを使用して意味するかもしれない本当に明確ではないが、それはまた、あなたが完全に異なる場合を意味する可能性があります。

操作は、一般に「無相関」のデータ検索を目的としており、さまざまなユースケースで役立ちます。これは、localFieldforeignFieldが2つのコレクション間で「結合」するように適用できる「相関」データとは対照的です。

述べたように、これは最良の例として実証DOCS-10298

で覆われています。これらのコレクションを作成してください:

db.related.insert([ 
    { "a": 1, "b": 2 }, 
    { "a": 2, "b": 2 }, 
    { "a": 3, "b": 3 } 
]) 

db.parent.insert({ 
    "name": "test", 
    "b": 2 
}) 

が、私はそうのような他のコレクションの項目に論理条件をテストするために、ここでpipelineletステートメントを使用することができます。

結果が得られます
db.parent.aggregate([ 
    { "$lookup": { 
    "from": "related", 
    "let": { 
     "b": "$b"  
    }, 
    "pipeline": [ 
     { "$addFields": { 
     "matched": { "$eq": [ "$$b", "$b" ] } 
     }} 
    ], 
    "as": "results" 
    }} 
]) 

:条件を示し

{ 
     "_id" : ObjectId("595332c28965d862ce61f451"), 
     "name" : "test", 
     "b" : 2, 
     "results" : [ 
       { 
         "_id" : ObjectId("59532b028965d862ce61f44d"), 
         "a" : 1, 
         "b" : 2, 
         "matched" : true 
       }, 
       { 
         "_id" : ObjectId("59532b028965d862ce61f44e"), 
         "a" : 2, 
         "b" : 2, 
         "matched" : true 
       }, 
       { 
         "_id" : ObjectId("59532b028965d862ce61f44f"), 
         "a" : 3, 
         "b" : 3, 
         "matched" : false 
       } 
     ] 
} 

カントーに対する親ドキュメントからletで宣言された変数に対して試験しましたこれらの製品は、付属のpipelineでテストされています。返す

db.parent.aggregate([ 
    { "$lookup": { 
    "from": "related", 
    "let": { 
     "b": "$b"  
    }, 
    "pipeline": [ 
     { "$redact": { 
     "$cond": { 
      "if": { "$eq": [ "$$b", "$b" ] }, 
      "then": "$$KEEP", 
      "else": "$$PRUNE" 
     } 
     }} 
    ], 
    "as": "results" 
    }} 
]) 

は、これは、$redactとして、あなたも「論理的」フィルターを使用することができます

{ 
     "_id" : ObjectId("595332c28965d862ce61f451"), 
     "name" : "test", 
     "b" : 2, 
     "results" : [ 
       { 
         "_id" : ObjectId("59532b028965d862ce61f44d"), 
         "a" : 1, 
         "b" : 2 
       }, 
       { 
         "_id" : ObjectId("59532b028965d862ce61f44e"), 
         "a" : 2, 
         "b" : 2 
       } 
     ] 
} 

しかし、もちろん、これはすでに導入された既存の機能で覆われていますMongoDB 3.2と通常の「相関」オプション:

db.parent.aggregate([ 
    { "$lookup": { 
    "from": "related", 
    "localField": "b", 
    "foreignField": "b", 
    "as": "results" 
    }} 
]) 

With上記と同じ結果になります。

db.parent.aggregate([ 
    { "$lookup": { 
    "from": "related", 
    "localField": "b", 
    "foreignField": "b", 
    "as": "results" 
    }}, 
    { "$unwind": "$results" }, 
    { "$match": { "results.a": 1 } } 
]) 

これは$lookup後、次の段階の集約パイプラインオプションは、実際に「掲揚されているので:あなたは、それは$unwind$matchを使用して書き込むために、実際に最も効率的だ、「追加条件」をしたい場合はもちろん

"を操作 $lookupに追加します。「説明」の出力に示されている:

{ 
      "$lookup" : { 
        "from" : "related", 
        "as" : "results", 
        "localField" : "b", 
        "foreignField" : "b", 
        "unwinding" : { 
          "preserveNullAndEmptyArrays" : false 
        }, 
        "matching" : { 
          "a" : { 
            "$eq" : 1 
          } 
        } 
      } 
    } 

これは、「巻き戻し」と「マッチング」の選択肢を示し、実際に$lookup内で適用されています。まだあなたはそれを直接書くことはできませんが、パイプラインの組み合わせはこの動作を適用します。

これは、実際には、16MBの上限を超えるエントリを持つ配列を作成した結果、BSON Limitが実質的に処理されないことになります。

ほとんどの場合、一般に既存の動作が必要で、新しいオプションは必要ありません。それでも。

+0

ありがとうNeil。 'let'を使うことは私が必要とするものです。私は 'let'を使って2つの変数(2つのキー)を定義し、それらを' pipeline'で使用して、結合されたコレクションの2つのフィールドと比較します。また、 '$ addFields'の代わりに' $ project'を使うときの違いはなんですか?それは私に同じ結果をもたらします。 –

+0

@KinCheungさて、彼らは異なっています。 '$ addFields'は、実際に"フィールドを "既存のドキュメントに追加しています。 '$ redact'のようなものはインデックスを使うことができないので、私はあなたが本当にあなたのケースでこれを必要としているとはまだ確信していません。最終的なフォームは「できます」。 –

関連する問題