mongodb得到不同的记录

时间:2011-02-23 09:41:10

标签: mongodb mongodb-scala

我正在使用mongoDB我收集了以下格式。

{"id" : 1 , name : x  ttm : 23 , val : 5 }
{"id" : 1 , name : x  ttm : 34 , val : 1 }
{"id" : 1 , name : x  ttm : 24 , val : 2 }
{"id" : 2 , name : x  ttm : 56 , val : 3 }
{"id" : 2 , name : x  ttm : 76 , val : 3 }
{"id" : 3 , name : x  ttm : 54 , val : 7 }

在那个集合中,我查询过这样的降序记录:

db.foo.find({"id" : {"$in" : [1,2,3]}}).sort(ttm : -1).limit(3)

但它提供了两个相同id = 1的记录,我希望记录为每id个记录。

mongodb有可能吗?

6 个答案:

答案 0 :(得分:25)

mongodb中有一个distinct命令,可以与查询一起使用。但是,我相信这只会为您命名的特定键返回一个不同的值列表(例如,在您的情况下,您只会返回返回的id值)所以我不确定这会给您完全符合您的要求需要整个文档 - 你可能需要MapReduce。

有关不同的文件: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct

答案 1 :(得分:15)

您想要使用聚合。你可以这样做:

db.test.aggregate([
    // each Object is an aggregation.
    {
        $group: {
            originalId: {$first: '$_id'}, // Hold onto original ID.
            _id: '$id', // Set the unique identifier
            val:  {$first: '$val'},
            name: {$first: '$name'},
            ttm:  {$first: '$ttm'}
        }

    }, {
        // this receives the output from the first aggregation.
        // So the (originally) non-unique 'id' field is now
        // present as the _id field. We want to rename it.
        $project:{
            _id : '$originalId', // Restore original ID.

            id  : '$_id', // 
            val : '$val',
            name: '$name',
            ttm : '$ttm'
        }
    }
])

对于我的100,000个文档的测试数据库,这将非常快...〜90ms。

示例:

db.test.find()
// { "_id" : ObjectId("55fb595b241fee91ac4cd881"), "id" : 1, "name" : "x", "ttm" : 23, "val" : 5 }
// { "_id" : ObjectId("55fb596d241fee91ac4cd882"), "id" : 1, "name" : "x", "ttm" : 34, "val" : 1 }
// { "_id" : ObjectId("55fb59c8241fee91ac4cd883"), "id" : 1, "name" : "x", "ttm" : 24, "val" : 2 }
// { "_id" : ObjectId("55fb59d9241fee91ac4cd884"), "id" : 2, "name" : "x", "ttm" : 56, "val" : 3 }
// { "_id" : ObjectId("55fb59e7241fee91ac4cd885"), "id" : 2, "name" : "x", "ttm" : 76, "val" : 3 }
// { "_id" : ObjectId("55fb59f9241fee91ac4cd886"), "id" : 3, "name" : "x", "ttm" : 54, "val" : 7 }


db.test.aggregate(/* from first code snippet */)

// output
{
    "result" : [
        {
            "_id" : ObjectId("55fb59f9241fee91ac4cd886"),
            "val" : 7,
            "name" : "x",
            "ttm" : 54,
            "id" : 3
        },
        {
            "_id" : ObjectId("55fb59d9241fee91ac4cd884"),
            "val" : 3,
            "name" : "x",
            "ttm" : 56,
            "id" : 2
        },
        {
            "_id" : ObjectId("55fb595b241fee91ac4cd881"),
            "val" : 5,
            "name" : "x",
            "ttm" : 23,
            "id" : 1
        }
    ],
    "ok" : 1
}

PROS:几乎可以肯定是最快的方法。

CONS:涉及使用复杂的聚合API。此外,它与文档的原始模式紧密耦合。但是,有可能概括一下。

答案 2 :(得分:7)

问题在于,您希望将3个匹配记录提取为1,而不在查询中提供任何逻辑,以了解如何在匹配结果之间进行选择。

您的选项基本上是指定某种聚合逻辑(例如,为每列选择最大值或最小值),或运行选择不同的查询并仅选择您希望区分的字段。

querymongo.com可以很好地为您翻译这些不同的查询(从SQL到MongoDB)。

例如,这个SQL:

SELECT DISTINCT columnA FROM collection WHERE columnA > 5

以MongoDB的形式返回:

db.runCommand({
    "distinct": "collection",
    "query": {
        "columnA": {
            "$gt": 5
        }
    },
    "key": "columnA"
});

答案 3 :(得分:6)

我相信你可以像这样使用聚合

collection.aggregate({
   $group : {
        "_id" : "$id",
        "docs" : { 
            $first : { 
            "name" : "$name",
            "ttm" : "$ttm",
            "val" : "$val",
            }
        } 
    }
});

答案 4 :(得分:2)

如果你想用javascript在文件中写出不同的结果......这就是你的做法

cursor = db.myColl.find({'fieldName':'fieldValue'})

var Arr = new Array();
var count = 0;

cursor.forEach(

function(x) {

    var temp = x.id;    
var index = Arr.indexOf(temp);      
if(index==-1)
   {
     printjson(x.id);
     Arr[count] = temp;
         count++;
   }
})

答案 5 :(得分:0)

指定与众不同的查询。 下面的示例从dept等于“ A”的文档中返回嵌入在item字段中的sku字段的不同值:

rebuildOnChange

参考:https://docs.mongodb.com/manual/reference/method/db.collection.distinct/