2017-06-28 14 views
1

我正在嘗試MongoDb 3.5.8中提供的新功能$lookuppipeline功能,並且想知道如何引用pipeline的父文檔中的字段。

我試圖比較父文檔中的兩個字段與查找文檔中的兩個字段。不知道如何做到這一點{$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

這真不明白你的意思在這裏是什麼,你有可能意味着使用letpipeline選項,但它也有可能你的意思是完全不同的情況。

pipeline操作通常用於「非相關」數據檢索,這在各種使用情況下都很有用。這與「關聯」數據相反,其中localFieldforeignField可以應用於兩個集合之間的「連接」。

如所提到的,這是覆蓋在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 
       } 
     ] 
} 

這表明該條件是針對來自父文檔的針對tho的聲明變量let進行測試的從pipeline提供的測試相關收集。

這可以讓你也可以使用一個「邏輯」過濾器如$redact

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

將返回:

{ 
     "_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與上面相同的結果。

當然,如果你想要的「附加條件」,那麼它實際上是最有效的使用$unwind$match寫:

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

這是因爲$lookup後以下階段聚合管道選項實際上是「升起「進入$lookup操作本身。證明在「解釋」輸出:

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

這說明「平倉」和「匹配」的選項實際上已經在$lookup內應用。到目前爲止,您不能直接編寫它,但管道組合會應用這種行爲。

事實上,這實際上是爲了基本上處理BSON限制不會因爲創建一個條目超過16MB上限的數組而導致中斷。

總之,在大多數情況下,您通常需要現有的行爲,並且不需要新的選項。然而。

+0

謝謝尼爾。使用'let'就是我需要的。我最終使用'let'來定義兩個變量(兩個鍵),然後在'pipeline'中使用它們來與連接集合中的兩個字段進行比較。另外,只是想知道在'$ addFields'處使用'$ project'時有什麼區別。它給了我相同的結果。 –

+0

@KinCheung他們是不同的。 '$ addFields'實際上是「向現有文檔添加字段」,就像我在答案中演示的那樣,如果仔細觀察的話。我仍然不確定你是否真的需要這樣做,並且你最好使用我在最後演示的那種想法,因爲像'$ redact'這樣的東西不能使用索引。最終形式「可以」。 –

相關問題