获取每个MongoDB聚合组的示例

时间:2016-10-30 16:13:17

标签: mongodb mongodb-query mongodb-aggregation

我有一个包含两个属性的MongoDB文档集合:type&值。

[
  {type: "A", value: "1"},
  {type: "A", value: "2"},
  {type: "B", value: "1"},
  {type: "B", value: "2"},
  {type: "C", value: "1"},
  {type: "C", value: "2"}
]

如何使用单个查询获取每种类型的随机文档?

我尝试使用聚合框架

来解决问题
db.collection.aggregate([
  {$group: {_id: "$type", item: {$push: "$$ROOT"}}},
  {$sample: {size: 1}}
]);

不对每个组应用采样,只是选择其中一个组。

3 个答案:

答案 0 :(得分:2)

或者,您可以迭代所有分组元素并以$sample之外的其他方式处理随机:

db.collection.aggregate([
    { $group: { _id: "$type", item: { $push: "$$ROOT" } } }
]).forEach(function(data) {
    var rand = data.item[Math.floor(Math.random() * data.item.length)];
    // insert in a new collection if needed
    // db.results.insert(rand);
    printjson(rand);
});

从数组中选择一个随机元素:Getting a random value from a JavaScript array

如果您的集合中有type的大不同值

,则此解决方案可能会很慢,因为它不使用聚合

答案 1 :(得分:0)

不确定这是否达到了您所寻找的目标,但我一直在尝试做类似的事情,我需要找到一组符合我标准的数据,然后从中获取随机样本。

我现在能够使用$ match和$ sample来实现这一点,如下所示:

db.collection('collectionname').aggregate(
{$match : {'type': 'B'}},
{$sample: {size: 1}}
);

答案 2 :(得分:0)

使用新的mapReduce框架,一种方法是执行此操作:

db.coll.mapReduce(
  /* group by type */
  function() { emit(this.type, this.value); },
  /* select one random index */
  function(u, vs) { return vs[Math.round(Math.random() * vs.length)]; },
  /* return the results directly, or use {out: "coll_name" } */
  {out: {inline: 1}} 
)

out参数也可以是集合的名称。结果:

{
    "results" : [
        {
            "_id" : "A",
            "value" : "2"
        },
        {
            "_id" : "B",
            "value" : "2"
        },
        {
            "_id" : "C",
            "value" : "1"
        }
    ],
    "timeMillis" : 24,
    "counts" : {
        "input" : 6,
        "emit" : 6,
        "reduce" : 3,
        "output" : 3
    },
    "ok" : 1
}