与skip()和limit()一起使用的Distinct()命令

时间:2013-04-17 09:02:20

标签: mongodb mongodb-java spring-data-mongodb

我在MongoDB集合中有这些项目:

{x: 1, y: 60, z:100}
{x: 1, y: 60, z:100}
{x: 1, y: 60, z:100}
{x: 2, y: 60, z:100}
{x: 2, y: 60, z:100}
{x: 3, y: 60, z:100}
{x: 4, y: 60, z:100}
{x: 4, y: 60, z:100}
{x: 5, y: 60, z:100}
{x: 6, y: 60, z:100}
{x: 6, y: 60, z:100}
{x: 6, y: 60, z:100}
{x: 7, y: 60, z:100}
{x: 7, y: 60, z:100}

我想查询x的不同值(即 [1,2,3,4,5,6,7] )...但我只想要它们的一部分(类似我们可以通过跳过(a)和限制(b)来获得。

如何使用MongoDB的java驱动程序(如果可能,使用spring-data-mongodb)?

2 个答案:

答案 0 :(得分:11)

使用聚合框架,mongo shell中的

很简单:

db.collection.aggregate([{$group:{_id:'$x'}}, {$skip:3}, {$limit:5}])

for java look:use aggregation framework in java

答案 1 :(得分:1)

根据您的使用情况,您可能会发现此方法比聚合更具效果。这是一个mongo shell示例函数。

function getDistinctValues(skip, limit) {

    var q = {x:{$gt: MinKey()}}; // query
    var s = {x:1};               // sort key

    var results = [];

    for(var i = 0; i < skip; i++) {
        var result = db.test.find(q).limit(1).sort(s).toArray()[0];
        if(!result) {
            return results;
        }
        q.x.$gt = result.x;
    }

    for(var i = 0; i < limit; i++) {
        var result = db.test.find(q).limit(1).sort(s).toArray()[0];
        if(!result) {
            break;
        }
        results.push(result.x);
        q.x.$gt = result.x;
    }

    return results;

}

我们基本上只是一次找到一个值,使用查询和排序来跳过我们已经看到的过去的值。您可以通过添加更多参数来轻松改进此功能,以使该功能更加灵活。此外,在要查找不同值的属性上创建索引将提高性能。

一个不那么明显的改进就是一起跳过“跳过”阶段并指定一个值来继续。这是一个mongo shell示例函数。

function getDistinctValues(limit, lastValue) {

    var q = {x:{$gt: lastValue === undefined ? MinKey() : lastValue}}; // query
    var s = {x:1};               // sort key

    var results = [];

    for(var i = 0; i < limit; i++) {
        var result = db.test.find(q).limit(1).sort(s).toArray()[0];
        if(!result) {
            break;
        }
        results.push(result.x);
        q.x.$gt = result.x;
    }

    return results;

}

如果您决定采用聚合技术,请确保在$ group阶段后添加$ sort阶段。否则,您的结果将不会以可预测的顺序显示。