Comment trier mongodb avec pymongo

164

J'essaie d'utiliser la fonction de tri lors de l'interrogation de mon mongoDB, mais cela échoue. La même requête fonctionne dans la console MongoDB mais pas ici. Le code est le suivant:

import pymongo

from  pymongo import Connection
connection = Connection()
db = connection.myDB
print db.posts.count()
for post in db.posts.find({}, {'entities.user_mentions.screen_name':1}).sort({u'entities.user_mentions.screen_name':1}):
    print post

L'erreur que j'obtiens est la suivante:

Traceback (most recent call last):
  File "find_ow.py", line 7, in <module>
    for post in db.posts.find({}, {'entities.user_mentions.screen_name':1}).sort({'entities.user_mentions.screen_name':1},1):
  File "/Library/Python/2.6/site-packages/pymongo-2.0.1-py2.6-macosx-10.6-universal.egg/pymongo/cursor.py", line 430, in sort
  File "/Library/Python/2.6/site-packages/pymongo-2.0.1-py2.6-macosx-10.6-universal.egg/pymongo/helpers.py", line 67, in _index_document
TypeError: first item in each key pair must be a string

J'ai trouvé un lien ailleurs qui dit que je dois placer un 'u' devant la clé si vous utilisez pymongo, mais cela n'a pas fonctionné non plus. N'importe qui d'autre fait fonctionner cela ou est-ce un bogue.

WildBill
la source

Réponses:

302

.sort(), en pymongo, prend keyetdirection comme paramètres.

Donc, si vous voulez trier, disons, idalors vous devriez.sort("_id", 1)

Pour plusieurs champs:

.sort([("field1", pymongo.ASCENDING), ("field2", pymongo.DESCENDING)])
Ben
la source
124
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])pour trier plusieurs champs.
richardr
4
Pour ceux qui recherchent plus de détails, voici un lien vers la documentation sur le tri avec pymongo api.mongodb.org/python/current/api/pymongo/…
Shane Reustle
21
NOTE: ascendant: 1, descendant -1
Martlark
2
Une idée de la raison pour laquelle ils ont massacré la notation JSON si simple {"field1": 1, "field2": 1}?
Nico
2
@Nico - voir la réponse de romulomadu ci
Bajal
34

Vous pouvez essayer ceci:

db.Account.find().sort("UserName")  
db.Account.find().sort("UserName",pymongo.ASCENDING)   
db.Account.find().sort("UserName",pymongo.DESCENDING)  
nouvelle lumière
la source
17

Cela fonctionne également:

db.Account.find().sort('UserName', -1)
db.Account.find().sort('UserName', 1)

J'utilise ceci dans mon code, veuillez commenter si je fais quelque chose de mal ici, merci.

Snehal Parmar
la source
Vous devez utiliser: ASCENDINGet DESCENDINGde pymongo. :)
Sn0pY
7

Pourquoi python utilise la liste des tuples à la place dict?

En python, vous ne pouvez pas garantir que le dictionnaire sera interprété dans l'ordre que vous avez déclaré.

Ainsi, dans mongo shell, vous pouvez le faire .sort({'field1':1,'field2':1})et l'interpréteur doit trier champ1 au premier niveau et champ 2 au deuxième niveau.

Si ce sintax a été utilisé en python, il est possible de trier field2 au premier niveau. Avec tuple, il n'y a aucun risque.

.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
romulomadu
la source
1
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])

Python utilise la clé, la direction. Vous pouvez utiliser la méthode ci-dessus.

Donc, dans votre cas, vous pouvez le faire

for post in db.posts.find().sort('entities.user_mentions.screen_name',pymongo.ASCENDING):
        print post
Ash Upadhyay
la source
0

TLDR: Le pipeline d'agrégation est plus rapide que le pipeline conventionnel .find().sort().

Passons maintenant à la vraie explication. Il existe deux façons d'effectuer des opérations de tri dans MongoDB:

  1. Utilisation .find()et .sort().
  2. Ou en utilisant le pipeline d'agrégation.

Comme le suggèrent de nombreux .find (). Sort () est le moyen le plus simple d'effectuer le tri.

.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])

Cependant, il s'agit d'un processus lent par rapport au pipeline d'agrégation.

Venir à la méthode du pipeline d'agrégation. Les étapes pour implémenter un pipeline d'agrégation simple destiné au tri sont les suivantes:

  1. $ match (étape facultative)
  2. $ sort

REMARQUE: d'après mon expérience, le pipeline d'agrégation fonctionne un peu plus rapidement que la .find().sort()méthode.

Voici un exemple de pipeline d'agrégation.

db.collection_name.aggregate([{
    "$match": {
        # your query - optional step
    }
},
{
    "$sort": {
        "field_1": pymongo.ASCENDING,
        "field_2": pymongo.DESCENDING,
        ....
    }
}])

Essayez vous-même cette méthode, comparez la vitesse et faites-le moi savoir dans les commentaires.

Edit: N'oubliez pas d'utiliser allowDiskUse=Truelors du tri sur plusieurs champs sinon cela générera une erreur.

Anuj Gupta
la source
0

Dites, vous voulez trier par champ 'created_on', alors vous pouvez faire comme ceci,

.sort('{}'.format('created_on'), 1 if sort_type == 'asc' else -1)
Md. Tanvir Raihan
la source