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.

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)])

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)  

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.


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)])

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

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.


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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.