2011-12-05 33 views
7

Necesito paginar una colección de artículos (ordenar por fecha, y nada más). ¿Cuál es la forma estándar de hacer algo como esto en Mongodb?¿Cómo implementar paginación en Mongodb?

No voy a utilizar el método skip() debido a problemas de rendimiento. Tampoco planeo usar el método $ push. El método más cercano que he visto es el método de consulta de rango. Pero parece fallar si se eliminan algunos de los elementos ordenados.

+2

Acepte la respuesta y cierre esta pregunta – beNerd

Respuesta

9

La clasificación de rangos debería funcionar bien para usted. Primera solicitud tomará primeros 10 elementos ordenados por fecha:

db.articles.find({}).sort({ date : -1 }).limit(10); 

Después de esto se necesita almacenar en algún lugar la fecha del último elemento y utilizar id en la próxima solicitud de localización:

db.articles.find({"date": {$lt: storedDateOfLastItem}}).sort({ date : -1 }).limit(10); 

lo tanto, supongo que debería trabaja bien para ti Para estimar el recuento total de páginas, deberá usar count.

Pero parece fallar si se eliminan algunos de los elementos ordenados.

Si va a eliminar, por ejemplo, el artículo de la página n. ° 1, con seguridad romperá la página n. ° 2 debido a que la última fecha almacenada se modificará. Para evitar esto se puede estimar el recuento de elementos que fue salvado antes de la fecha actual

db.articles.find({"date": {$gt: storedDateOfLastItem}}).sort({ date : -1 }).count() 

Si esta cuenta se ha cambiado (vamos a decir 2 articled fue eliminado). Usted necesita actualizado storedDateOfLastItem

db.articles.find({"date": {$gt: storedDateOfLastItem}}).sort({ date : -1 }).take(2) 

Una vez más tomar storedDateOfLastItem del último elemento de la mencionada solicitud y continuar a hacer paginación.

Pero mi opinión solo es mantener esta paginación sin lógica adicional, porque supongo que la eliminación del artículo es una operación rara.

De la documentación mongodb:

Costos de paginación Desafortunadamente skip puede ser (muy) costoso y requiere el servidor a pie desde el inicio de la recolección, o el índice, para obtener al desplazamiento de posición/saltar antes de que pueda comenzar a devolver la página de datos (límite). A medida que el número de página aumenta, el salto se volverá más lento y más intensivo en la CPU, y posiblemente IO obligado, con colecciones más grandes.

La paginación basada en rangos proporciona un mejor uso de los índices pero no permite que salte fácilmente a una página específica.

+0

Las consultas de rango/marcadores de página que usan tipos de fecha no funcionan, ya que obtendrá inconsistencias para varios registros con la misma fecha. Yo usaría _id marcadores de valor en su lugar para esto. Todo lo que dijo esto es mucho trabajo de limpieza solo para evitar el rendimiento de o (N) por omisión (N). –

+0

Ahhhh es tan aburrido en mongodb? Deseo que alguien de 10gen nos muestre cómo recomiendan la búsqueda. –

+0

@LulZilla: Mire mi actualización, es de la documentación de mongodb. –

0

Si puede ordenar en un índice, la paginación eficiente se puede implementar usando los modificadores de consulta "$ min" y "$ max" o una consulta de rango. Asegúrese de que su índice incluya una propiedad única al final (por ejemplo, "_id").

Si no puede ordenar en un índice, puede preprocesar el conjunto completo de resultados y mantener una lista de los valores "_id" en orden. Luego puede tomar un rango de esa lista y buscar una página de resultados usando el operador de consulta "$ in".

Cuestiones relacionadas