计算已排序分页的给定记录的跳过值

时间:2015-07-06 09:59:16

标签: php mongodb mongodb-query mongodb-php

我试图使用php驱动程序计算mongo db集合中给定记录的跳过值。因此,获取给定记录,找出整个集合中该记录的索引。这可能吗?

目前,我选择所有记录并手动对结果数组进行索引。

1 个答案:

答案 0 :(得分:5)

这称为“前向分页”,这是一个概念,可用于在使用“已排序”结果时以“向前”方向“有效地”搜索结果。

包含JavaScript逻辑(因为它在shell中工作),但不难翻译。

一般概念:

{ "_id": 1, "a": 3 },
{ "_id": 2, "a": 3 },
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }

考虑那些“已经排序”的文件(为方便起见)作为我们希望每页“两个”项目“页面”的结果示例。

首先你做这样的事情:

var lastVal = null,
    lastSeen = [];

db.collection.find().sort({ "a": -1 }).limit(2).forEach(function(doc) {
    if ( lastVal != doc.a ) {
        lastSeen = [];
    }
    lastVal = doc.a;
    lastSeen.push( doc._id );
    // do something useful with each document matched
});

现在,lastVallastSeen存储的内容类似于“会话变量”,而不是可以在Web应用程序的下一个请求中访问,或者其他类似的地方。 / p>

它们应包含的内容是您排序的最后一个值,以及自该值未发生变化后看到的“唯一”_id值列表。因此:

lastVal = 3,
lastSeen = [1,2];

关键是,当出现“下一页”的请求时,你想要将这些变量用于这样的事情:

var lastVal = 3,
    lastSeen = [1,2];

db.collection.find({ 
    "_id": { "$nin": lastSeen }, 
    "a": { "$lte": lastVal }
}).sort({ "a": -1 }).limit(2).forEach(function(doc) {
    if ( lastVal != doc.a ) {
        lastSeen = [];
    }
    lastVal = doc.a;
    lastSeen.push( doc._id );
    // do something useful with each document matched
});

它的作用是“排除”结果列表中_id中记录的lastSeen的所有值,并确保所有结果都必须“小于或等于“(降序)为排序字段”a“记录的lastVal

这将产生集合中的下两个结果:

{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },

但在处理完我们的价值后,现在看起来像这样:

lastVal = 2,
lastSeen = [4];

所以现在的逻辑是,您不需要排除之前看到的其他_id值,因为您只是真正寻找“a”的值而不是“小于或等于”{{ 1}}因为在该值处只看到“一个”lastVal值,所以只排除那个值。

这当然会产生下一页使用与上面相同的代码:

_id

这是通过结果“转发页面”的最有效方式,对于有效分页“排序”结果特别有用。

如果您想在任何阶段“跳转”到页面{ "_id": 5, "a": 1 }, { "_id": 6, "a": 0 } 或类似的操作,那么这不适合您。您仍然坚持使用传统的20.skip()方法,以便能够通过“页码”执行此操作,因为没有其他合理的方法来“计算”此内容。

所以这一切都取决于您的应用程序如何实现“分页”以及您可以使用的内容。 .limit().skip()方法会受到“跳过”的影响,可以通过此处使用此方法来避免。

另一方面,如果你想“跳转到页面”,那么“跳过”是你唯一真正的选择,除非你想建立一个结果的“缓存”。但这完全是另一个问题。