Question

Quand j'ai essayé de trier une collection un champ de chaîne (ici Title), le tri ne fonctionne pas comme prévu. Veuillez voir ci-dessous:

db.SomeCollection.find().limit(50).sort({ "Title" : -1 });

Ordre de résultat réel

  • "Titre": "Geog.3 Book des étudiants"
  • "Titre": "Geog.2 Book des étudiants"
  • "Titre": "Geog.1 Book des étudiants"
  • "Titre": "Zoe et Swift"
  • "Titre": "Zip au parc à thème"
  • "Titre": "Zip au supermarché"

Ordonnance de résultats attendue

  • "Titre": "Zoe et Swift"
  • "Titre": "Zip au parc à thème"
  • "Titre": "Zip au supermarché"
  • "Titre": "Geog.3 Book des étudiants"
  • "Titre": "Geog.2 Book des étudiants"
  • "Titre": "Geog.1 Book des étudiants"

Les mêmes problèmes se produisent lorsque j'ai essayé de trier par champ de date.

Aucune suggestion?

Était-ce utile?

La solution

Mise à jour: La version 3.4 a Index insensibles au cas

C'est un problème connu. MongoDB ne prend pas en charge le tri lexical pour les chaînes (Jira: String Lexicographical Order). Vous devez trier les résultats dans votre code d'application ou trier à l'aide d'un champ numérique. Il devrait cependant trier les champs de date de manière fiable. Pouvez-vous donner un exemple où le tri par date ne fonctionne pas?

Autres conseils

Qu'est-ce qui vous surprend exactement?

Il trie basé sur la présentation de la représentation numérique du symbole. Si tu vas regarder ici (Je sais que MongoDB stocke des cordes dans UTF-8, donc c'est juste à des fins éducatives). Vous verrez que les lettres supérieures ont des numéros correspondants inférieurs aux lettres en minuscules. Ainsi, ils iront devant.

MongoDB ne peut pas trier les lettres en fonction de la localisation ou de la cas insensible.

Dans ton cas g a alors un nombre plus élevé Z, il va donc en premier (tri par ordre décroissant). Et alors 3 a un nombre correspondant plus élevé alors 2 et 1. Donc, fondamentalement, tout est correct.

Si vous utilisez l'agrégation, la sortie attendue est possible, voir ci-dessous:

    db.collection.aggregate([
    { 
        "$project": {
           "Title": 1,        
           "output": { "$toLower": "$Title" }       
        }},
        { "$sort": {  "output":-1 } },
        {"$project": {"Title": 1, "_id":0}}
    ])


ça te donnera production attendue Comme ci-dessous:

    {
        "result" : [ 
            {
                "Title" : "Zoe and Swift"
            }, 
            {
                "Title" : "Zip at the Theme Park"
            }, 
            {
                "Title" : "Zip at the Supermarket"
            }, 
            {
                "Title" : "geog.3 students' book"
            }, 
            {
                "Title" : "geog.2 students' book"
            }, 
            {
                "Title" : "geog.1 students' book"
            }
        ],
        "ok" : 1
    }

En commençant par les dates qui ne trient pas correctement ...

Si vous stockez une date en tant que string, il doit être triable en tant que chaîne. C'est assez simple:

2013-11-08  // yyyy-mm-dd (the dashes would be optional)

Tant que chaque pièce de la chaîne de date est rembourrée avec 0 À juste titre, les cordes seront toutes sorties naturellement et dans la façon dont vous vous attendez.

Un temps de date complet est stocké en UTC généralement:

2013-11-23T10:46:01.914Z

Mais, je vous suggérerais également au lieu de stocker une valeur de date en tant que chaîne, vous considérez si l'utilisation d'une date de mongodb native aurait plus de sens (référence). Si vous regardez le cadre d'agrégation de Mongodb, vous trouverez qu'il y en a beaucoup les fonctions Cela peut manipuler ces dates, tandis qu'une chaîne est très limitée.

En ce qui concerne le tri des chaînes, il a été souligné qu'il est de tri comme un ordinateur stocke les données plutôt que la façon dont vous triez en tant que personne. Si vous considérez que la chaîne est stockée comme sa représentation ASCII / UTF-8, vous devriez voir pourquoi le tri fonctionne comme:

Zoe = [90, 111, 101]
geo = [103, 101, 111]

Si vous deviez les trier en ordre décroissant comme vous l'avez spécifié, vous devriez voir comment "geo"La représentation des octets internes est plus grande que celle de la chaîne "Zoe" (avec 103 tri plus élevé que 90 dans ce cas).

En règle générale, la recommandation lors de l'utilisation de MongoDB est de stocker les cordes deux fois si vous avez besoin de trier une chaîne qui a un cas mixte:

  1. Chaîne d'origine ("Title")
  2. Comme une chaîne normalisée. Peut-être par exemple, tous comme "minuscules", éventuellement avec des caractères accentués également convertis en un caractère commun. Donc, vous vous retrouveriez avec un nouveau champ nommé "SortedTitle" Par exemple et votre code l'utiliserait pour trier, mais affiche le réel "Title" aux utilisateurs.

Si vous faites à Ror et Mongomapper, suivez les étapes ci-dessous:

J'ai pris le nom de mon modèle ABC et récupéré le résultat pour le titre.

@test_abc_details_array_full=Abc.collection.aggregate([

     {"$project"=> {
       "Title"=> 1,        
       "output"=> { "$toLower"=> "$Title" }       
    }},
    { "$sort"=> {  "output"=>1 } },        
    {"$project"=> {Title: 1, _id:0}},

  ]); 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top