【问题标题】:Distinct() command used with skip() and limit()与 skip() 和 limit() 一起使用的 Distinct() 命令
【发布时间】:2013-04-09 23:15:35
【问题描述】:

我的 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) 和 limit(b) 获得的结果。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    Java 外观:use aggregation framework in java

    【讨论】:

    • 来自 mongo jira (2017):“如果你有 7 百万个文档并且你执行了 collection.aggregate([{$group : {_id : "$field"}},{$limit: 1}])您将等待约 20 秒。” jira.mongodb.org/browse/…
    • @duhaime 你可以添加索引。 db.collection.createIndex({"x": 1}).
    【解决方案2】:

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

    【讨论】:

    • 这对性能不好。您将向数据库发送 limit 请求,而不是 1 个聚合请求。
    猜你喜欢
    • 2012-06-19
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多