Jak posortować mongodb za pomocą pymongo

164

Próbuję użyć funkcji sortowania podczas wysyłania zapytań do mojej bazy danych mongoDB, ale kończy się to niepowodzeniem. To samo zapytanie działa w konsoli MongoDB, ale nie tutaj. Kod jest następujący:

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

Otrzymuję następujący błąd:

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

Znalazłem link w innym miejscu, który mówi, że muszę umieścić „u” przed kluczem, jeśli używam pymongo, ale to też nie zadziałało. Ktoś inny sprawi, że to zadziała, czy to jest błąd.

WildBill
źródło

Odpowiedzi:

302

.sort(), w pymongo, przyjmuje keyi directionjako parametry.

Więc jeśli chcesz sortować według, powiedzmy, idpowinieneś.sort("_id", 1)

W przypadku wielu pól:

.sort([("field1", pymongo.ASCENDING), ("field2", pymongo.DESCENDING)])
Ben
źródło
124
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])aby posortować wiele pól.
richardr
4
Dla tych, którzy szukają więcej szczegółów, tutaj jest link do dokumentacji na temat sortowania za pomocą pymongo api.mongodb.org/python/current/api/pymongo/ ...
Shane Reustle
21
UWAGA: rosnąco: 1, malejąco -1
Martlark
2
Masz jakiś pomysł, dlaczego zmasakrowali tak prostą notację {"field1": 1, "field2": 1} JSON?
Nico
2
@Nico - zobacz odpowiedź romulomadu poniżej
Bajal
34

Możesz spróbować tego:

db.Account.find().sort("UserName")  
db.Account.find().sort("UserName",pymongo.ASCENDING)   
db.Account.find().sort("UserName",pymongo.DESCENDING)  
nowe światło
źródło
17

Działa to również:

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

Używam tego w moim kodzie, proszę o komentarz, jeśli robię coś źle, dzięki.

Snehal Parmar
źródło
Powinieneś użyć: ASCENDINGi DESCENDINGfrom pymongo. :)
Sn0pY
7

Dlaczego Python używa listy krotek zamiast dyktować?

W Pythonie nie możesz zagwarantować, że słownik zostanie zinterpretowany w zadeklarowanej kolejności.

Tak więc w powłoce mongo możesz to zrobić, .sort({'field1':1,'field2':1})a interpreter powinien posortować pole 1 na pierwszym poziomie, a pole 2 na drugim poziomie.

Jeśli ten sintax był używany w Pythonie, istnieje szansa na sortowanie field2 na pierwszym poziomie. W przypadku krotki nie ma ryzyka.

.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
romulomadu
źródło
1
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])

Python używa klucza, kierunku. Możesz skorzystać z powyższego sposobu.

Więc w twoim przypadku możesz to zrobić

for post in db.posts.find().sort('entities.user_mentions.screen_name',pymongo.ASCENDING):
        print post
Ash Upadhyay
źródło
0

TLDR: potok agregacji jest szybszy w porównaniu z konwencjonalnym .find().sort().

A teraz przejdźmy do prawdziwego wyjaśnienia. Istnieją dwa sposoby wykonywania operacji sortowania w MongoDB:

  1. Korzystanie .find()i .sort().
  2. Lub za pomocą potoku agregacji.

Jak sugeruje wiele .find (). Sort () jest najprostszym sposobem wykonania sortowania.

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

Jest to jednak proces powolny w porównaniu z potokiem agregacji.

Przechodząc do metody potoku agregacji. Kroki wdrażania prostego potoku agregacji przeznaczonego do sortowania są następujące:

  1. $ match (krok opcjonalny)
  2. $ sort

UWAGA: Z mojego doświadczenia wynika, że ​​potok agregacji działa nieco szybciej niż .find().sort()metoda.

Oto przykład potoku agregacji.

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

Wypróbuj tę metodę samodzielnie, porównaj prędkość i daj mi znać w komentarzach.

Edycja: Nie zapomnij użyć allowDiskUse=Truepodczas sortowania na wielu polach, w przeciwnym razie spowoduje to błąd.

Anuj Gupta
źródło
0

Powiedzmy, że chcesz posortować według pola „created_on”, możesz to zrobić,

.sort('{}'.format('created_on'), 1 if sort_type == 'asc' else -1)
Md. Tanvir Raihan
źródło