6

我的 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])......但我只想要其中的一部分(类似于我们可以使用 skip(a)和限制(b))。

我如何使用 MongoDB 的 java 驱动程序(或者如果可能的话使用 spring-data-mongodb)来做到这一点?

4

2 回答 2

14

在 mongo shell 中使用聚合框架很简单:

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

对于 java 外观:在 java 中使用聚合框架

于 2013-04-17T09:16:29.693 回答
0

根据您的用例,您可能会发现这种方法比聚合更高效。这是一个 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 阶段。否则,您的结果将不会以可预测的顺序显示。

于 2014-11-07T17:29:53.390 回答