MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB $sort

Dans MongoDB, le $sort l'étape de pipeline d'agrégation trie tous les documents d'entrée et les renvoie au pipeline dans l'ordre trié.

Syntaxe

La syntaxe ressemble à ceci :

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } } 

<sort order> peut être 1 pour l'ascendant, -1 pour décroissant, ou { $meta: "textScore" } pour trier par le textScore calculé métadonnées par ordre décroissant.

Exemple de données

Supposons que nous ayons une collection appelée pets avec les documents suivants :

{ "_id" :1, "name" :"Wag", "type" :"Chien", "weight" :20 }{ "_id" :2, "name" :"Bark", "type" :"Chien", "poids" :10 }{ "_id" :3, "nom" :"Miaou", "type" :"Chat", "poids" :7 }{ "_id" :4, "nom" :"Scratch", "type" :"Chat", "weight" :8 }{ "_id" :5, "name" :"Bruce", "type" :"Kangaroo", "weight" :100 }{ " _id" :6, "name" :"Hop", "type" :"Kangaroo", "weight" :130 }{ "_id" :7, "name" :"Punch", "type" :"Kangaroo", "weight" :200 }{ "_id" :8, "name" :"Snap", "type" :"Cat", "weight" :12 }{ "_id" :9, "name" :"Ruff", "type" :"Chien", "poids" :30 }

Trier par ordre croissant

Pour trier par ordre croissant, nous utilisons 1 pour l'ordre de tri.

Ci-dessous un exemple de requête qui utilise le $sort opérateur pour trier cette collection par le weight champ par ordre croissant.

db.pets.aggregate([
    { $sort: { weight: 1 } } 
]) 

Résultat :

{ "_id" :3, "name" :"Meow", "type" :"Chat", "weight" :7 }{ "_id" :4, "name" :"Scratch", "type" :"Chat", "poids" :8 }{ "_id" :2, "nom" :"Aboiement", "type" :"Chien", "poids" :10 }{ "_id" :8, "nom" :"Snap", "type" :"Chat", "weight" :12 }{ "_id" :1, "name" :"Wag", "type" :"Chien", "weight" :20 }{ " _id" :9, "name" :"Ruff", "type" :"Chien", "weight" :30 }{ "_id" :5, "name" :"Bruce", "type" :"Kangourou", "weight" :100 }{ "_id" :6, "name" :"Hop", "type" :"Kangaroo", "weight" :130 }{ "_id" :7, "name" :"Punch", "type" :"Kangourou", "poids" :200 }

Trier par ordre décroissant

Pour trier par ordre décroissant, nous utilisons -1 pour l'ordre de tri.

db.pets.aggregate([
    { $sort: { weight: -1 } } 
]) 

Résultat :

{ "_id" :7, "name" :"Punch", "type" :"Kangaroo", "weight" :200 }{ "_id" :6, "name" :"Hop", "type" :"Kangourou", "poids" :130 }{ "_id" :5, "nom" :"Bruce", "type" :"Kangourou", "poids" :100 }{ "_id" :9, "nom" :"Ruff", "type" :"Chien", "weight" :30 }{ "_id" :1, "name" :"Wag", "type" :"Chien", "weight" :20 }{ " _id" :8, "name" :"Snap", "type" :"Chat", "weight" :12 }{ "_id" :2, "name" :"Bark", "type" :"Chien", "weight" :10 }{ "_id" :4, "name" :"Scratch", "type" :"Cat", "weight" :8 }{ "_id" :3, "name" :"Meow", "type" :"Chat", "poids" :7 }

Trier par plusieurs champs

Pour trier sur plusieurs champs, séparez chaque combo champ/ordre de tri par une virgule.

Exemple

db.pets.aggregate([
    { $sort: { type: 1, weight: -1, _id: 1 } }
]) 

Résultat :

{ "_id" :8, "name" :"Snap", "type" :"Cat", "weight" :12 }{ "_id" :4, "name" :"Scratch", "type" :"Chat", "poids" :8 }{ "_id" :3, "nom" :"Miaou", "type" :"Chat", "poids" :7 }{ "_id" :9, "nom" :"Ruff", "type" :"Chien", "weight" :30 }{ "_id" :1, "name" :"Wag", "type" :"Chien", "weight" :20 }{ " _id" :2, "name" :"Bark", "type" :"Chien", "weight" :10 }{ "_id" :7, "name" :"Punch", "type" :"Kangourou", "weight" :200 }{ "_id" :6, "name" :"Hop", "type" :"Kangaroo", "weight" :130 }{ "_id" :5, "name" :"Bruce", "type" :"Kangourou", "poids" :100 }

Dans cet exemple, nous avons trié par le type champ dans l'ordre croissant d'abord, puis par le weight champ par ordre décroissant, puis par le _id champ par ordre croissant.

Cela signifie que, s'il y a plusieurs animaux du même type, ces animaux sont triés par leur weight par ordre décroissant. S'il y a plusieurs animaux avec le même type et le même poids, alors ces animaux sont triés par le _id champ par ordre croissant. Si nous n'avions pas inclus le _id champ dans le processus de tri, ces animaux du même type et du même poids pourraient apparaître dans n'importe quel ordre. Cela est vrai à chaque fois que nous exécutons la requête. Sans avoir un champ de tri sur un champ unique (comme le _id champ), il serait tout à fait possible (voire probable) que les résultats reviennent dans un ordre différent à chaque exécution de la requête.

Trier différents types

Lors de la comparaison des valeurs de différents types de BSON, MongoDB utilise l'ordre de comparaison suivant, du plus bas au plus élevé :

  1. MinKey (type interne)
  2. Nul
  3. Nombres (entiers, longs, doubles, décimaux)
  4. Symbole, Chaîne
  5. Objet
  6. Tableau
  7. BinData
  8. ObjectId
  9. Booléen
  10. Date
  11. Horodatage
  12. Expression régulière
  13. MaxKey (type interne)

Supposons que nous ayons une collection appelée posts avec les documents suivants :

{ "_id" :1, "title" :"Web", "body" :"Créez un site web en trois étapes simples...", "date" :"2021-01-01T00:00:00.000 Z"}{ "_id" :2, "title" :"Animaux", "body" :"Les animaux sont de drôles de choses...", "date" :ISODate("2020-01-01T00:00:00Z") }{ "_id" :3, "title" :"Océans", "body" :"Les océans sont larges et vastes...", "date" :ISODate("2021-01-01T00:00:00Z")} 

Notez que la première date contient une chaîne de date, alors que les deux autres documents utilisent un objet Date.

Notez également que la chaîne de date contient exactement la même date que le document 3 et que cette date est postérieure à la date du document 2.

Appliquons $sort à la date champs de ces documents :

db.posts.aggregate([
    { $sort: { date: 1 } } 
]).pretty() 

Résultat :

{ "_id" :1, "title" :"Web", "body" :"Créez un site web en trois étapes simples...", "date" :"2021-01-01T00:00:00.000 Z"}{ "_id" :2, "title" :"Animaux", "body" :"Les animaux sont de drôles de choses...", "date" :ISODate("2020-01-01T00:00:00Z") }{ "_id" :3, "title" :"Océans", "body" :"Les océans sont larges et vastes...", "date" :ISODate("2021-01-01T00:00:00Z")} 

Dans ce cas, nous avons trié par ordre croissant, ce qui signifie que les dates les plus anciennes doivent venir en premier. Cependant, notre premier document contient une chaîne de date au lieu d'un objet Date, et il est donc venu en premier - même si sa date est postérieure à la date du document 2.

La voici à nouveau, mais dans l'ordre décroissant :

db.posts.aggregate([
    { $sort: { date: -1 } } 
]).pretty() 

Résultat :

{ "_id" :3, "title" :"Océans", "body" :"Les océans sont larges et vastes...", "date" :ISODate("2021-01-01T00:00:00Z" )}{ "_id" :2, "title" :"Animaux", "body" :"Les animaux sont de drôles de choses...", "date" :ISODate("2020-01-01T00:00:00Z")} { "_id" :1, "title" :"Web", "body" :"Créez un site web en trois étapes simples...", "date" :"2021-01-01T00:00:00.000Z"} 

Encore une fois, l'ordre des dates est déséquilibré, en raison des différents types de données.

Trier les métadonnées de score de texte

Vous pouvez utiliser le { $meta: "textScore" } argument pour trier par score de pertinence décroissant lors de l'utilisation de $text recherches.

Exemple

db.posts.aggregate(
   [
     { $match: { $text: { $search: "funny" } } },
     { $sort: { score: { $meta: "textScore" }, title: -1 } }
   ]
).pretty() 

Résultat :

{ "_id" :2, "title" :"Animaux", "body" :"Les animaux sont de drôles de choses...", "date" :ISODate("2020-01-01T00:00:00Z") } 

Dans ce cas, un seul document correspondait à notre requête.

Dans cet exemple, nous avons trié par { $meta: "textScore" } , puis par title par ordre décroissant. Nous avons utilisé score comme un nom de champ arbitraire, mais cela est ignoré par le système de requête.

Faire $text des recherches comme celle-ci nécessitent que nous ayons créé un index de texte. Sinon, un IndexNotFound l'erreur sera renvoyée.

Trier les résultats groupés

Revenons à nos pets collection, nous pouvons utiliser le $sort étape après un $group étape pour trier un groupe de documents en fonction du nombre de valeurs dans un champ particulier.

db.pets.aggregate([
    {
      $match: { weight: { $lt: 30 } }
    },
    {
      $group: { _id: "$type", count: { $sum: 1 } }
    },
     { 
      $sort : { count : -1 } 
    }
]) 

Résultat :

{ "_id" :"Chat", "count" :3 }{ "_id" :"Chien", "count" :2 }

Cependant, vous feriez peut-être mieux d'utiliser le $sortByCount opérateur dans de tels cas.

Plus d'informations

Consultez la documentation MongoDB pour plus d'informations.