75 votes

MongoDB - pagination

Lorsque vous utilisez MongoDB, existe-t-il des modèles spéciaux pour créer, par exemple, une vue paginée ? Par exemple, un blog qui liste les 10 derniers articles et dans lequel on peut naviguer vers les articles plus anciens.

Ou bien peut-on résoudre ce problème avec un index sur, par exemple, blogpost.publishdate et simplement sauter et limiter le résultat ?

95voto

Scott Hernandez Points 4300

L'utilisation de skip+limit n'est pas une bonne façon de faire de la pagination lorsque les performances sont un problème, ou avec de grandes collections ; cela deviendra de plus en plus lent au fur et à mesure que vous augmenterez le nombre de pages. L'utilisation de la fonction "skip" oblige le serveur à parcourir tous les documents (ou valeurs d'index) de 0 à la valeur de décalage (skip).

Il est préférable d'utiliser une requête de plage (+ limite) dans laquelle vous transmettez la valeur de la plage de la dernière page. Par exemple, si vous triez par "date de publication", il vous suffit de passer la dernière valeur "date de publication" comme critère de la requête pour obtenir la page suivante de données.

11voto

jackalope Points 525
  1. La pagination basée sur la plage est difficile à mettre en œuvre si vous devez trier les éléments de plusieurs façons.
  2. Rappelez-vous que si la valeur du champ du paramètre de tri n'est pas unique, la pagination basée sur la plage ne sera pas réalisable.

Solution possible : essayer de simplifier le design, en pensant à trier uniquement par id ou par une valeur unique ?

Et si c'est le cas, alors on peut utiliser le pageing basé sur la gamme.

La méthode la plus courante consiste à utiliser les fonctions sort() , skip() et limit() pour mettre en œuvre la pagination décrite ci-dessus.

1voto

whardier Points 118

La pagination basée sur la plage est faisable, mais vous devez être intelligent sur la façon dont vous miner/maxer la requête.

Si vous pouvez vous le permettre, vous devriez essayer de mettre en cache les résultats d'une requête dans un fichier ou une collection temporaire. Grâce aux collections TTL de MongoDB, vous pouvez insérer vos résultats dans deux collections.

  1. Recherche+Utilisateur+Paramètres Requête (TTL quelconque)
  2. Résultats de la requête (TTL quelconque + intervalle de nettoyage + 1)

L'utilisation des deux assure que vous n'obtiendrez pas de résultats partiels lorsque le TTL est proche de l'heure actuelle. Vous pouvez utiliser un simple compteur lorsque vous stockez les résultats pour effectuer une requête de plage TRÈS simple à ce moment-là.

1voto

Alex Ho Points 11

Voici un exemple de la récupération d'une liste de User documents commandés par CreatedDate (où pageIndex est basée sur zéro) en utilisant le pilote C# officiel.

public void List<User> GetUsers() 
{
  var connectionString = "<a connection string>";
  var client = new MongoClient(connectionString);
  var server = client.GetServer();
  var database = server.GetDatabase("<a database name>");

  var sortBy = SortBy<User>.Descending(u => u.CreatedDate);
  var collection = database.GetCollection<User>("Users");
  var cursor = collection.FindAll();
  cursor.SetSortOrder(sortBy);

  cursor.Skip = pageIndex * pageSize;
  cursor.Limit = pageSize;
  return cursor.ToList();
}

Toutes les opérations de tri et de pagination sont effectuées du côté du serveur. Bien qu'il s'agisse d'un exemple en C#, je suppose que la même chose peut s'appliquer aux ports d'autres langages.

Voir http://docs.mongodb.org/ecosystem/tutorial/use-csharp-driver/#modifying-a-cursor-before-enumerating-it .

0voto

YordanGeorgiev Points 1222
    // file:ad-hoc.js
    // an example of using the less binary as pager in the bash shell
    //
    // call on the shell by:
    // mongo localhost:27017/mydb ad-hoc.js | less
    //
    // note ad-hoc.js must be in your current directory
    // replace the 27017 wit the port of your mongodb instance
    // replace the mydb with the name of the db you want to query
    //
    // create the connection obj
    conn = new Mongo();

    // set the db of the connection
    // replace the mydb with the name of the db you want to query
    db = conn.getDB("mydb");

    // replace the products with the name of the collection
    // populate my the products collection
    // this is just for demo purposes - you will probably have your data already
    for (var i=0;i<1000;i++ ) {
    db.products.insert(
        [
            { _id: i, item: "lamp", qty: 50, type: "desk" },
        ],
        { ordered: true }
    )
    }

    // replace the products with the name of the collection
    cursor = db.products.find();

    // print the collection contents
    while ( cursor.hasNext() ) {
        printjson( cursor.next() );
    }
    // eof file: ad-hoc.js

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X