2011-04-02 17 views
17

Probablemente me falta algo, ya que todavía estoy aprendiendo las ins y outs de MongoDB, pero necesito ayuda para buscar una colección.¿Cómo hacer paginación usando consultas de rango en MongoDB?

Tengo una colección que tiene una lista de nombres.

fondo redondo de ternera
mama pollo 6 oz
mama pollo 8 oz
mama pollo 8 oz
mama pollo 8 oz
de mama pollo azar
piernas de pollo
pollo lomo
muslos de pollo
Sal Kosher

Creé un índice compuesto en "ProductName, _id".

que ejecuta esta consulta:

artículos
db.ProductGuideItem.find({ ProductName: { $gt: "Chicken Breast 8oz" } }).sort({ProductName:1,_id:1}).limit(3); 

Advertencia Hay 3 "8 oz pechuga de pollo".

Si me quedo esa consulta consigo ...
mama pollo azar
piernas de pollo
pollo lomo

si yo era de paginación y comenzó desde la parte superior. La consulta habría perdido y la otra 2 "pechuga de pollo 8oz".

Así que si cada página sólo puede tener 3 artículos y quiero ver página 2 entonces yo debería ver ..
mama pollo 8 oz
mama pollo 8 oz aleatoria
pechuga de pollo.

Pero no lo soy. Va al último Chicken Breast 8oz y comienza desde allí.

¿Hay alguna forma de evitar esto?
También, ¿cómo podría hacer esto si la lista se ordenó de la manera opuesta?

+1

¿Cuál es su reclamo? Las tres filas devueltas están perfectamente bien y coinciden con su consulta o ¿qué espera y por qué? –

+0

Primero que nada relájate. Obviamente no estoy explicando esto correctamente. Si cada página solo puede tener 3 elementos y quiero ver la página 2, entonces debería ver Pechuga de pollo con 8 oz, Pechuga de pollo con 8 oz, Pechuga de pollo al azar. Pero yo no. Va a la última Chicken Breast 8oz y comienza desde allí. –

+0

Como lo estoy haciendo mal, ¿cómo podría obtener la página 2 con los elementos que enumeré? –

Respuesta

27

Como la colección que estaba buscando tenía valores duplicados, tuve que crear un índice compuesto en ProductName e id.

Crear Índice Compuesto

db.ProductGuideItem.ensureIndex({ ProductName:1, _id:1}); 

Esto resolvió mi problema.
Referencia: https://groups.google.com/d/msg/mongodb-user/3EZZIRJzW_A/oYH79npKZHkJ

Asumiendo que tiene estos valores:

{a:1, b:1} 
{a:2, b:1} 
{a:2, b:2} 
{a:2, b:3} 
{a:3, b:1} 

Por lo que hace esto por la paginación basada gama (tamaño de página de 2):

primera página

find().sort({a:1, b:1}).limit(2) 
{a:1, b:1} 
{a:2, b:1} 

segunda página

find().min({a:2, b:1}).sort({a:1, b:1}).skip(1).limit(2) 

{a:2, b:2} 
{a:2, b:3} 

tercera página

find().min({a:2, b:3}).sort({a:1, b:1}).skip(1).limit(2) 
{a:3, b:1} 

Éstos son los documentos de $ min/max: http://www.mongodb.org/display/DOCS/min+and+max+Query+Specifiers

Si usted no tiene valores duplicados en su colección, no necesita usar min & max o crear un índice compuesto. Solo puede usar $ lt & $ gt.

+0

Creo que esta es una perspectiva interesante y útil para la paginación basada en rango en campos no únicos. Sin embargo, no creo que su índice compuesto sea de gran utilidad si el campo _id es parte de la consulta. La razón es que el campo _id es único y automáticamente podrá usar el índice _id predeterminado en lugar del índice compuesto. Consulte aquí el razonamiento http://stackoverflow.com/questions/9598633/mongodb-unique-index-vs-compound-index –

+0

Al usar este método, debe forzar a mongodb a usar el índice '{ProductName: 1, _id: 1} 'Si no lo haces, tus resultados estarán fuera de servicio. –

+0

Esto no es adecuado para la paginación donde muestra un componente de paginación (por ejemplo, 'Página 1, Página 2, Página 3, ..., Página 10') para el usuario, ya que no puede hacer clic aleatoriamente en un enlace 'Página # N' , porque para que funcione, primero necesitarías el último 'ObjectID' para' Page # N-1'. Esto es más apropiado para páginas de "desplazamiento infinito" como Google+, Facebook o Twitter. – Behrang

5

sólo tiene que llamar a saltar en el cursor

ver la documentación en MongoDB cursor skip "Este enfoque puede ser útil en la aplicación‘’Resultados" paginados.

Este ejemplo está tomado de MongoDB de example

function printStudents(pageNumber, nPerPage) { 
    print("Page: " + pageNumber); 
    db.students.find().skip((pageNumber-1)*nPerPage).limit(nPerPage).forEach(function(student) { print(student.name + "<p>"); }); 
} 
Cuestiones relacionadas