2015-06-06 36 views
1

我有一個MongoDB的集合,投票與下面的模式貓鼬聚集如何做嵌套數組文件

{ 
"options" : [ 
       { 
       "_id" : Object Id, 
       "option" : String, 
       "votes" : [ Object Id ] // object ids of users who voted 
       },..... 
      ] 
} 

假設我有節點JS用戶的用戶id我向他們要發這個信息。我的任務是

(1)在上面的json對象(我​​使用貓鼬)中包含一個額外的字段。

「myVote」:option._id

我需要找到option._id針對

選項[someIndex] .votes包含用戶id

(2)更改每個選項中現有的「投票」字段,以表示特定選項的投票數例如,在可見

例子:

{ 
    "options" : [ 
       { 
       "_id" : 1, 
       "option" : "A", 
       "votes" : [ 1,2,3 ] 
       }, 
       { 
       "_id" : 2, 
       "option" : "B", 
       "votes" : [ 5 ] 
       }, 
       { 
       "_id" : 3, 
       "option" : "C", 
       "votes" : [ ] 
       } 
      ] 
} 

所以,如果一個用戶ID爲我的用戶= 5希望看到投票的話,我需要發送以下信息:

預期結果:

{ 
    "my_vote" : 2,   // user with id 5 voted on option with id 2 
    "options" : [ 
       { 
       "_id" : 1, 
       "option" : "A", 
       "votes" : 3    //num of votes on option "A" 
       }, 
       { 
       "_id" : 2, 
       "option" : "B", 
       "votes" : 1    //num of votes on option "B" 
       }, 
       { 
       "_id" : 3, 
       "option" : "C", 
       "votes" : 0   //num of votes on option "C" 
       } 
      ] 
} 
+1

嘿?你想要什麼?請嘗試添加您嘗試過的內容以及預期的結果。 –

+0

這裏的例子和結果看起來與發佈的原始結構高度不一致。另外,「id = 5」怎麼會因此而發揮作用呢?在您選擇添加附加信息時,「標記」向您發表評論的人也是習慣和禮貌的要求。幫助人們知道你在做什麼。 –

+1

@ user3561036對不起abt之前沒有標記,預期的結果實際上是我想發送給客戶端的json。我認爲這可以通過使用聚合框架來實現,但由於我是新手,無法編寫精確查詢 –

回答

1

因爲它是你居然問,既不真正在當前接受的答案提供,也在於它做了一些不必要的東西,還有另一種方法的問題:

var userId = 5; // A variable to work into the submitted pipeline 

db.sample.aggregate([ 
    { "$unwind": "$options" }, 
    { "$group": { 
     "_id": "$_id", 
     "my_vote": { "$min": { 
      "$cond": [ 
       { "$setIsSubset": [ [userId], "$options.votes" ] }, 
       "$options._id", 
       false 
      ] 
     }}, 
     "options": { "$push": { 
      "_id": "$options._id", 
      "option": "$options.option", 
      "votes": { "$size": "$options.votes" } 
     }} 
    }} 
]) 

這當然會給每個文檔輸出你這樣的:

{ 
    "_id" : ObjectId("5573a0a8b67e246aba2b4b6e"), 
    "my_vote" : 2, 
    "options" : [ 
      { 
        "_id" : 1, 
        "option" : "A", 
        "votes" : 3 
      }, 
      { 
        "_id" : 2, 
        "option" : "B", 
        "votes" : 1 
      }, 
      { 
        "_id" : 3, 
        "option" : "C", 
        "votes" : 0 
      } 
    ] 
} 

所以,你在這裏做什麼,以先分解爲檢查陣列使用$unwind。以下$group階段(以及唯一需要的其他階段)利用$min$push運營商進行重新構建。

內每個這些操作的,該操作$cond測試經由$setIsSubset陣列內容,要麼返回匹配_id值或false。在重建內部數組元素時,請指定$push的參數中的所有元素,而不僅僅是頂級文檔,並使用$size運算符來計算數組中的元素。

您還提到了另一個關於與$unwind處理空數組問題的鏈接。這裏的$size運營商將做正確的事情,所以它不需要$unwind,並在這種情況下投射數組爲空的「虛擬」值。


大注,除非你實際上是通過它通常會建議在客戶端代碼,而不是聚合框架做這個操作文件「聚集」。使用$unwind可有效地爲每個文檔中包含的每個數組元素在聚合管道中創建一個新文檔,這會產生大量開銷。

對於僅對不同文檔執行操作的操作,客戶端代碼更有效地分別處理每個文檔。


如果你真的要堅持該服務器的處理是這樣做的方法,那麼這可能是最有效的使用$map代替:

db.sample.aggregate([ 
    { "$project": { 
     "my_vote": { 
      "$setDifference": [ 
       { "$map": { 
        "input": "$options", 
        "as": "o", 
        "in": { "$cond": [ 
         { "$setIsSubset": [ [userId], "$$o.votes" ] }, 
         "$$o._id", 
         false 
        ]} 
       }}, 
       [false] 
      ] 
     }, 
     "options": { "$map": { 
      "input": "$options", 
      "as": "o", 
      "in": { 
       "_id": "$$o._id", 
       "option": "$$o.option", 
       "votes": { "$size": "$$o.votes" } 
      } 
     }} 
    }} 
]) 

所以這只是「工程」再加工結果爲每個文件。該my_vote是不一樣的,雖然,因爲它是單一元件陣列(或可能的多個匹配),該聚合框架缺少運營商降低到非數組元素沒有進一步的開銷:

{ 
    "_id" : ObjectId("5573a0a8b67e246aba2b4b6e"), 
    "options" : [ 
      { 
        "_id" : 1, 
        "option" : "A", 
        "votes" : 3 
      }, 
      { 
        "_id" : 2, 
        "option" : "B", 
        "votes" : 1 
      }, 
      { 
        "_id" : 3, 
        "option" : "C", 
        "votes" : 0 
      } 
    ], 
    "my_vote" : [ 
      2 
    ] 
} 
0

Check out this question

這不是要求同樣的事情,但沒有辦法做你沒有多重查詢無論如何要求。 我會修改您直接返回的JSON,因爲您只是顯示查詢結果中已包含的額外信息。

  1. 保存您要查詢的userID
  2. 取出查詢結果(對象中的選項數組),搜索數組中每個元素的votes
  3. 當您找到合適的投票時,請附上_id(如果您沒有找到投票,可能會添加'n/a')。

寫,做2和3的功能,並且你可以通過它userID,並得到一個新的對象附有myVote

我不認爲這樣做會比在Mongoose中做另一個查詢要慢。