计算给定记录的跳过值以进行分页 [英] Calculate skip value for given record for sorted paging

查看:39
本文介绍了计算给定记录的跳过值以进行分页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to calculate the skip value for a given record in a mongo db collection using the php driver. So taking a given record, find out the index of that record within the entire collection. Is this possible?

当前,我正在选择所有记录,并手动在结果数组上做一个索引.

Currently I'm selecting all records and manually doing an index of on the array of results.

推荐答案

这称为转发分页",当您使用排序"结果时,可以使用该概念在转发"方向上对结果进行有效分页".

This is called "forward paging" which is a concept you can use to "efficiently page" through results in a "forward" direction when using "sorted" results.

包含了JavaScript逻辑(因为它可以在shell中使用),但是翻译起来并不难.

JavaScript logic included (because it works in the shell), but not hard to translate.

一般概念:

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

以那些已经排序"的文档(为方便起见)为例,我们希望每页按两个"项目分页".

Consider those "already sorted" documents ( for convienience ) as an example of results we want to "page" by "two" items per page.

首先,您需要执行以下操作:

In the first instance you do something like this:

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应用程序而言,下一个请求可以访问这些东西,否则就不会存在.

Now those lastVal and lastSeen are something you store in something like a "session variable" than can be accessed on the next request in terms of web applications, or otherwise something similar where not.

尽管它们应该包含的是您正在排序的最后一个值,以及由于该值未更改而出现的唯一" _id值列表.因此:

What they should contain though are the very last value you were sorting on and the list of "unique" _id values that were seen since that value did not change. Hence:

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

关键是,当对下一页"的请求出现时,您想将这些变量用于类似这样的事情:

The point is that when the request for the "next page" comes around then you want to use those variables for something like this:

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
});

这样做是从结果列表中排除" lastSeen中记录的所有_id值,并确保所有结果都必须小于或等于"(降序)为排序字段"a"记录的lastVal.

What that does is "exclude" all values of _id that are recorded in lastSeen from the list of results, as well as make sure that all results need to be "less than or equal to" ( descending order ) the lastVal recorded for the sort field "a".

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

This yields the next two results in the collection:

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

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

But after processing our values now look like this:

lastVal = 2,
lastSeen = [4];

因此,现在的逻辑是,您不需要排除之前看到的其他_id值,因为您只真正在寻找"a"值而不是小于或等于" lastVal和因为在该值上只能看到一个"_id"值,所以只能排除该值.

So now the logic follows that you don't need to exclude the other _id values seen before since you are only really looking for values of "a" than are "less than or equal to" the lastVal and since there was only "one" _id value seen at that value then only exclude that one.

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

This of course yields the next page on using the same code as just above:

{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }


通常,这是通过结果转发页面"的最有效方法,对于有效分页排序的"结果特别有用.


That is the most effiecient way to "forward page" through results in general and is particularly useful for efficient paging of "sorted" results.

但是,如果您想在任何阶段跳转"到页面20或类似操作,则此方法不适合您.您无法使用传统的.skip().limit()方法来按页码"执行此操作,因为没有其他合理的方法可以计算"此结果.

If however you want to "jump" to page 20 or similar action at any stage then this is not for you. You are stuck with the traditional .skip() and .limit() approach to be able to do this by "page number" since there is no other rational way to "calculate" this.

因此,这一切都取决于您的应用程序如何实现分页"以及可以使用的内容. .skip().limit()方法具有跳过"的性能,可以通过使用此处的方法来避免.

So it all depends on how your application is implementing "paging" and what you can live with. The .skip() and .limit() approach suffers the performance of "skipping" and can be avoided by using the approach here.

另一方面,如果要跳转到页面",那么除非要建立结果的缓存",否则跳过"是唯一的选择.但这完全是另一个问题.

On the other hand, if you want "jump to page" then "skipping" is your only real option unless you want to build a "cache" of results. But that's another issue entirely.

这篇关于计算给定记录的跳过值以进行分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆