2017-05-29 75 views
0

我有一個集合,其中包含兩種類型的文檔。基於我想要執行查找聚合的文檔類型。只有當本地域存在時才執行條件查找?

Action是一個集合,它包含對話和消息類型的動作。我想根據MongoDB中的字段對對話和消息進行不同的查找。

談話式的操作文件是如下的消息

{ 
    "_id" : ObjectId("592bdeaf45c7201421793871"), 
    "actionType" : "message", 
    "created" : NumberInt(1496047280), 
    "messageId" : ObjectId("592bdeaf45c7201421793870") 
} 

我希望有一個特定的時間之後的行動和要執行的查找來獲得對話和消息數據

{ 
    "_id" : ObjectId("592bdeaf45c7201421793871"), 
    "actionType" : "conversation", 
    "created" : NumberInt(1496047280), 
    "users" : [ 
     ObjectId("590c53a85fba594a59fe3d0f"), 
     ObjectId("590c50175df715499129e41b") 
    ], 
    "conversationId" : ObjectId("592bdeaf45c7201421793870"), 
    "missionId" : ObjectId("590c50fa5df715499129e41c") 
} 

行動文件從他們的對象ID。

我想這

let matchQuery = { 
      users : new ObjectId(userId), 
      created: 
      { 
       $gt : createdTime 
      }}; 

     let aggregation = [ 
      { 
      $match : matchQuery 
      }, 
      {$cond : 
      {if: 
       { 
       $users:{ 
        $exists:true 
       } 
      }, 
      then: { 
      $unwind : "$users", 
      $lookup: { 
       from : "users", 
       localfield:"$users", 
       foreignfield:"_id", 
       as:"userDetail" 
         }, 
      $group:{ 
        "users" : { $push : "userDetail"} 
        } 
        } 
       } 
      }, 
      {$cond : 
      {if: 
       { 
       $conversationId:{ 
        $exists:true 
       } 
      }, 
      then: { 
      $lookup : { 
          from:"conversations", 
          localfield:"conversationId", 
          foreignfield:"_id", 
          as:"conversationDetail" 
          } 
        } 
       } 
      }, 
      {$cond : 
      {if: 
       { 
       $missionId:{ 
        $exists:true 
       } 
      }, 
      then: { 
      $lookup : { 
          from:"services_v2", 
          localfield:"missionId", 
          foreignfield:"_id", 
          as:"missionDetail" 
          } 
        } 
       } 
      }, 
      {$cond : 
      {if: 
       { 
       $messageId:{ 
        $exists:true 
       } 
      }, 
      then: { 
      $lookup : { 
          from:"messagev2", 
           localfield:"messageId", 
           foreignfield:"_id", 
           as:"messageDetail" 
          } 
        } 
       } 
      }, 
      { 
      $project : { 
       "_id" : 1, 
       "actionType" : 1, 
       "userDetail":1, 
       "conversationDetail":1, 
       "missionDetail":1, 
       "messageDetail":1 
}} 
     ]; 

connection.collection('actions') 
.aggregate(aggregation).toArray((err,result)=> { 
    if(err){ 
     console.log(err); 
    } 
    console.log(result); 
}) 
}; 
+0

我試過了開關,但它不能識別查找或展開表達式。 –

+0

在你的問題中顯示你正在談論的內容。使用一些真實的文件並顯示預期的結果。在你的問題上使用[編輯](https://stackoverflow.com/posts/44241188/edit)鏈接,而不是添加評論。 –

+0

用代碼更新了它。 –

回答

1

我認爲你這一點,並得太多,你並不需要一個「條件查詢」,它可能是最好的例子來說明。

採取單獨收集這些文件中,第一次談話:

> db.conversation.find() 
{ "_id" : ObjectId("592ccbf8fceb6b40e6489759"), "message" : "I'm here" } 

然後消息採集:

> db.message.find() 
{ "_id" : ObjectId("592ccc0bfceb6b40e648975a"), "text" : "Something here" } 

然後,我有一個主集合,有每個這些文件的引用單獨的文件:

> db.master.find() 
{ 
    "_id" : ObjectId("592ccc73fceb6b40e648975b"), 
    "a" : 1, 
    "conversation" : ObjectId("592ccbf8fceb6b40e6489759") 
} 
{ 
    "_id" : ObjectId("592ccc95fceb6b40e648975c"), 
    "a" : 2, 
    "message" : ObjectId("592ccc0bfceb6b40e648975a") 
} 

現在,如果我做一個$lookup操作(這有點類似於一個「左連接」):

db.master.aggregate([ 
    { "$lookup": { 
    "from": "conversation", 
    "localField": "conversation", 
    "foreignField": "_id", 
    "as": "conversation" 
    }} 
]) 

然後我得到這樣的,這當然突出於文檔空數組的結果是沒有一個"localField"匹配:

{ 
    "_id" : ObjectId("592ccc73fceb6b40e648975b"), 
    "a" : 1, 
    "conversation" : [ 
     { 
      "_id" : ObjectId("592ccbf8fceb6b40e6489759"), 
      "message" : "I'm here" 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("592ccc95fceb6b40e648975c"), 
    "a" : 2, 
    "message" : ObjectId("592ccc0bfceb6b40e648975a"), 
    "conversation" : [ ] 
} 

如果我現在添加到管道中的「第二」 $lookup操作鏈接到消息採集:

db.master.aggregate([ 
    { "$lookup": { 
    "from": "conversation", 
    "localField": "conversation", 
    "foreignField": "_id", 
    "as": "conversation" 
    }}, 
    { "$lookup": { 
    "from": "message", 
    "localField": "message", 
    "foreignField": "_id", 
    "as": "message" 
    }} 
]) 

然後,我們看到了simila [R效果,即不具有該屬性的文件,現在有一個空數組,但其屬性確實存在,我們現在已經從特定集合的條目:

{ 
    "_id" : ObjectId("592ccc73fceb6b40e648975b"), 
    "a" : 1, 
    "conversation" : [ 
     { 
      "_id" : ObjectId("592ccbf8fceb6b40e6489759"), 
      "message" : "I'm here" 
     } 
    ], 
    "message" : [ ] 
} 
{ 
    "_id" : ObjectId("592ccc95fceb6b40e648975c"), 
    "a" : 2, 
    "message" : [ 
     { 
      "_id" : ObjectId("592ccc0bfceb6b40e648975a"), 
      "text" : "Something here" 
     } 
    ], 
    "conversation" : [ ] 
} 

您可以離開這個,因爲它是(這似乎是你嘗試過什麼到目前爲止所期望的最終狀態),還是現在做其他操作它,如合併成一個單一陣列:

db.master.aggregate([ 
    { "$lookup": { 
    "from": "conversation", 
    "localField": "conversation", 
    "foreignField": "_id", 
    "as": "conversation" 
    }}, 
    { "$lookup": { 
    "from": "message", 
    "localField": "message", 
    "foreignField": "_id", 
    "as": "message" 
    }}, 
    { "$project": { 
    "a": 1, 
    "combined": { 
     "$concatArrays": [ 
     { "$map": { 
      "input": "$conversation", 
      "as": "el", 
      "in": { 
      "type": "conversation", 
      "_id": "$$el._id", 
      "message": "$$el.message" 
      } 
     }}, 
     { "$map": { 
      "input": "$message", 
      "as": "el", 
      "in": { 
      "type": "message", 
      "_id": "$$el._id", 
      "text": "$$el.text" 
      } 
     }} 
     ] 
    } 
    }} 
]) 

,其輸出爲:

{ 
    "_id" : ObjectId("592ccc73fceb6b40e648975b"), 
    "a" : 1, 
    "combined" : [ 
     { 
      "type" : "conversation", 
      "_id" : ObjectId("592ccbf8fceb6b40e6489759"), 
      "message" : "I'm here" 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("592ccc95fceb6b40e648975c"), 
    "a" : 2, 
    "combined" : [ 
     { 
      "type" : "message", 
      "_id" : ObjectId("592ccc0bfceb6b40e648975a"), 
      "text" : "Something here" 
     } 
    ] 
} 

如果"localField""foreignField"表達式與任何元素都不匹配,那麼$lookup將非常有意地簡單地留下「空arrray」。這不會影響除了爲目標添加空數組屬性之外返回的文檔結果。

現在,您可以使用$unwind「鬆動」文檔,但這也只會在您忽略"preserveNullAndEmptyArrays"選項時發生,該選項用於處理此類事件。

但是,對於基於$lookup的「鑑別器」的一般用法,那麼對每個想要「鏈接」的集合使用單獨的管道階段。

+0

你說的正確。還發現mongo支持多個數組查找,因此我不需要爲用戶再次放鬆和分組。也因爲使用「localfield」而不是「localField」的愚蠢錯誤:D。再次感謝:) –

+0

有什麼辦法可以讓他們作爲對象,而不是一個數組?我也不想返回空字段。另外,我希望每個細節都嵌套在一個字段下,而不像它是如何呈現的。 –

+1

@HemantKumarGoyal如果你有另一個問題,然後[問一個新的問題](https://stackoverflow.com/questions/ask)。無論如何,這是解釋你的意圖和期望輸出的最好方式。 –

相關問題