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

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

问题描述

我正在尝试使用 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 是您存储在类似会话变量"的东西中的东西,可以在网络应用程序的下一个请求中访问,或者以其他方式类似的地方没有.

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天全站免登陆