2016-04-28 103 views
3

我正在寻找一种方式来获取数据,如该如何将文档分组到数组元素的索引上?

{ "_id" : 5, "count" : 1, "arr" : [ "aga", "dd", "a" ] }, 
{ "_id" : 6, "count" : 4, "arr" : [ "aga", "ysdf" ] }, 
{ "_id" : 7, "count" : 4, "arr" : [ "sad", "aga" ] } 

我想总结基础上改编的第一个项目(指数)的数量。在另一个集合中,我想对arr数组中的第一个和第二个项目执行相同操作。

我试过使用展开,但分解数据和层次结构然后丢失。

我也使用

$group: { 
    _id: { 
     arr_0:'$arr.0' 
    }, 
    total:{ 
     $sum: '$count' 
    } 
} 

尝试,但结果是空白阵列

回答

2

其实你可以不指定索引处的元素使用dot notation将你的文件。到两个你有两个选择:

首先在MongoDB 3.2中使用$arrayElemAt运算符new的最佳方式。它返回数组中指定索引处的元素。

db.collection.aggregate([ 
    { "$group": { 
     "_id": { "$arrayElemAt": [ "$arr", 0 ] }, 
     "count": { "$sum": 1 } 
    }} 
]) 

从MongoDB的3.0版本落后,你将需要由_id然后去正常化您的阵列在第一时间$group和使用$first操作到阵列中返回的第一个项目。从那里你将需要使用该值重新组合文档,并使用$sum来获得总和。但是这只适用于第一个和最后一个索引,因为MongoDB还提供了$last运算符。

db.collection.aggregate([ 
    { "$unwind": "$arr" }, 
    { "$group": { 
     "_id": "$_id", 
     "arr": { "$first": "$arr" } 
    }}, 
    { "$group": { 
     "_id": "$arr", 
     "count": { "$sum": 1 } 
    }} 
]) 

其产生是这样的:在p位置

{ "_id" : "sad", "count" : 1 } 
{ "_id" : "aga", "count" : 2 } 

要使用元组数组中,你将使用mapReduce功能得到更好的机会。

var mapFunction = function(){ emit(this.arr[0], 1); }; 
var reduceFunction = function(key, value) { return Array.sum(value); }; 
db.collection.mapReduce(mapFunction, reduceFunction, { "out": { "inline": 1 } }) 

将返回:

{ 
     "results" : [ 
       { 
         "_id" : "aga", 
         "value" : 2 
       }, 
       { 
         "_id" : "sad", 
         "value" : 1 
       } 
     ], 
     "timeMillis" : 27, 
     "counts" : { 
       "input" : 3, 
       "emit" : 3, 
       "reduce" : 1, 
       "output" : 2 
     }, 
     "ok" : 1 
} 
+0

感谢,我一直在寻找像'$ arrayElemAt'。我认为这可能是更好的选择,因为我认为在数组中添加第二个元素会更容易,通过这样做......'{arr_0:{$ arrayElemAt:[$ arr,0]},arr_1:{$ arrayElemAt :[$ arr,1]},} – Daniel

+0

@Daniel yes'$ arrayElemAt'绝对是最好的选择。顺便说一句,你应该考虑接受答案。 – styvane

相关问题