php - paginar - Calcular el valor de omisión para un registro dado para paginación ordenada
php mongodb driver manager (1)
Estoy tratando de calcular el valor de omisión para un registro dado en una colección mongo db usando el controlador php. Entonces, tomando un registro dado, descubra el índice de ese registro dentro de toda la colección. es posible?
Actualmente estoy seleccionando todos los registros y haciendo manualmente un índice de la matriz de resultados.
Esto se denomina "paginación hacia adelante", que es un concepto que puede usar para "buscar eficientemente" a través de los resultados en una dirección "hacia adelante" al usar resultados "ordenados".
Incluye lógica de JavaScript (porque funciona en el shell), pero no es difícil de traducir.
El concepto en general:
{ "_id": 1, "a": 3 },
{ "_id": 2, "a": 3 },
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
Considere esos documentos "ya ordenados" (por conveniencia) como un ejemplo de resultados que queremos "paginar" por "dos" elementos por página.
En primera instancia, haces algo como esto:
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
});
Ahora esos
lastVal
y
lastSeen
son algo que almacena en algo así como una "variable de sesión" a la que se puede acceder en la próxima solicitud en términos de aplicaciones web, o de otra manera algo similar donde no.
Sin embargo, lo que deberían contener es el último valor que estaba ordenando y la lista de valores
_id
"únicos" que se vieron desde que ese valor no cambió.
Por lo tanto:
lastVal = 3,
lastSeen = [1,2];
El punto es que cuando llega la solicitud de la "página siguiente", entonces desea usar esas variables para algo como esto:
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
});
Lo que hace es "excluir" todos los valores de
_id
que se registran en
lastSeen
de la lista de resultados, así como asegurarse de que todos los resultados deben ser "menores o iguales a" (orden descendente) el
lastVal
registrado para la clasificación campo "a".
Esto produce los siguientes dos resultados en la colección:
{ "_id": 3, "a": 3 },
{ "_id": 4, "a": 2 },
Pero después de procesar nuestros valores ahora se ven así:
lastVal = 2,
lastSeen = [4];
Así que ahora la lógica sigue que no necesita excluir los otros valores
_id
vistos anteriormente, ya que solo está buscando valores de "a" que sean "menores o iguales que" el
lastVal
y dado que solo había "uno"
_id
valor visto en ese valor entonces solo excluye ese.
Por supuesto, esto produce la siguiente página sobre el uso del mismo código que el anterior:
{ "_id": 5, "a": 1 },
{ "_id": 6, "a": 0 }
Esa es la forma más eficiente de "reenviar la página" a través de los resultados en general y es particularmente útil para la paginación eficiente de los resultados "ordenados".
Sin embargo, si desea "saltar" a la página
20
o una acción similar en cualquier etapa, entonces esto no es para usted.
Está atascado con el
.skip()
tradicional
.skip()
y
.limit()
para poder hacer esto por "número de página" ya que no hay otra forma racional de "calcular" esto.
Por lo tanto, todo depende de cómo su aplicación está implementando la "paginación" y con qué puede vivir.
El
.skip()
y
.limit()
sufre el rendimiento de "omitir" y puede evitarse usando el enfoque aquí.
Por otro lado, si desea "saltar a la página", entonces "omitir" es su única opción real a menos que desee crear un "caché" de resultados. Pero ese es otro problema completamente.