2016-07-07 41 views
5

我有什麼:串聯數組元素與聚合框架

{ "_id" : ObjectId("577dc9d61a0b7e0a40499f90"), "equ" : 123456, "key" : "p" } 
{ "_id" : ObjectId("577c789b1a0b7e0a403f1b52"), "equ" : 123456, "key" : "r" } 
{ "_id" : ObjectId("577b27481a0b7e0a4033965a"), "equ" : 123456, "key" : "r" } 
{ "_id" : ObjectId("5779d6111a0b7e0a40282dc7"), "equ" : 123456, "key" : "o" } 

我想要什麼:

{ "_id" : ObjectId("5779d6111a0b7e0a40282dc7"), "equ" : 123456, "keys" : "prro" } 

我試了一下:

db.table.aggregate([{"$group":{"_id":0, "keys":{"$push":"$key"}}}]) 返回一個arr ay而不是字符串:

{"_id":0, "keys":["p","r","r","o"]} 

你有什麼想法嗎?

+0

爲什麼你選擇'ObjectId(「5779d6111a0b7e0a40282dc7」)'?既然是最後一個? –

+0

不要考慮ObjectId。我不在乎身份證,只有證件和鑰匙事宜。 – hotips

+1

然後沒有必要保持最後的ID,然後投影它,就像我在我的答案 –

回答

9

TL; DR

使用該聚合管道:

db.col.aggregate([ 
    {$group: {_id: "$equ", last: {$last: "$_id"}, keys: {$push: "$key"}}}, 
    { 
     $project: { 
      equ: "$_id", 
      _id: "$last", 
      keys: { 
       $reduce: { 
        input: "$keys", 
        initialValue: "", 
        in: {$concat: ["$$value", "$$this"]} 
       } 
      } 
     } 
    } 
]) 

更多細節

首先,你應該group基礎上,equ價值的文件,並保持與last group member_id沿array of keys

var groupByEqu = { 
    $group: { 
     _id: "$equ", 
     last: {$last: "$_id"}, 
     keys: {$push: "$key"} 
    } 
} 

只把它運用流水線操作會導致:

{ 
    "_id" : 123456, 
    "last" : ObjectId("5779d6111a0b7e0a40282dc7"), 
    "keys" : [ "p", "r", "r", "o" ] 
} 

您應該使用投影前面文檔轉換成你想要的一個。前兩個轉變是微不足道的。對於加入數組元素,你可以使用新的$reduce操作:

var project = { 
    $project: { 
     equ: "$_id", 
     _id: "$last", 
     keys: { 
      $reduce: { 
       input: "$keys", 
       initialValue: "", 
       in: {$concat: ["$$value", "$$this"]} 
      } 
     } 
    } 
} 

應用這兩個流水線作業會給你想要的結果:

db.col.aggregate([groupByEqu, project]) 

那就是:

{ 
    "equ" : 123456, 
    "_id" : ObjectId("5779d6111a0b7e0a40282dc7"), 
    "keys" : "prro" 
}