Distinct() command used with skip() and limit()

左心房为你撑大大i 提交于 2019-12-10 13:19:17

问题


I have those items in my MongoDB collection:

{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}

I want to query the distinct values of x (i.e. [1, 2, 3, 4, 5, 6, 7]) ... but I only want a part of them (similar to what we can obtain with skip(a) and limit(b)).

How do I do that with the java driver of MongoDB (or with spring-data-mongodb if possible) ?


回答1:


in mongo shell is simple with aggregate framework:

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

for java look: use aggregation framework in java




回答2:


Depending on your use case, you may find this approach to be more performant than aggregation. Here's a mongo shell example function.

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;

}

We are basically just finding the values one at a time, using the query and sort to skip past values we have already seen. You can easily improve on this by adding more arguments to make the function more flexible. Also, creating an index on the property you want to find distinct values for will improve performance.

A less obvious improvement would be to skip the "skip" phase all together and specify a value to continue from. Here's a mongo shell example function.

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;

}

If you do decide to go with the aggregation technique, make sure you add a $sort stage after the $group stage. Otherwise your results will not show up in a predictable order.



来源:https://stackoverflow.com/questions/16055868/distinct-command-used-with-skip-and-limit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!