Як сортувати mongodb з pymongo


164

Я намагаюся використовувати функцію сортування під час запиту мого mongoDB, але це не вдається. Цей самий запит працює і в консолі MongoDB, але не тут. Код такий:

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

Отримана помилка полягає в наступному:

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

У іншому місці я знайшов посилання, в якому сказано, що мені потрібно поставити ключ 'u' перед використанням ключа pymongo, але це не спрацювало. Хто-небудь інший змусить це працювати або це помилка.

Відповіді:


302

.sort(), в pymongo, приймає keyі directionяк параметри.

Отже, якщо ви хочете сортувати за, скажімо, idтоді вам слід.sort("_id", 1)

Для кількох полів:

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

124
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])сортувати кілька полів.
richardr

4
Для тих, хто шукає більше деталей, тут посилання на документацію щодо сортування за допомогою pymongo api.mongodb.org/python/current/api/pymongo/…
Shane Reustle

21
ПРИМІТКА: висхідний: 1, низхідний -1
Martlark

2
Будь-яка ідея, чому вони вирізали так легко {"field1": 1, "field2": 1} JSON позначення?
Ніко

2
@Nico - див. Відповідь romulomadu нижче
Bajal

34

Ви можете спробувати це:

db.Account.find().sort("UserName")  
db.Account.find().sort("UserName",pymongo.ASCENDING)   
db.Account.find().sort("UserName",pymongo.DESCENDING)  

17

Це також працює:

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

Я використовую це у своєму коді, будь ласка, прокоментуйте, якщо я роблю тут щось не так, дякую.


Ви повинні використовувати: ASCENDINGі DESCENDINGз pymongo. :)
Sn0pY

7

Чому python використовує список кортежів, а не диктант?

У python ви не можете гарантувати, що словник буде інтерпретований у визначеному вами порядку.

Отже, в оболонці монго ви могли б зробити .sort({'field1':1,'field2':1})і перекладач повинен сортувати field1 на першому рівні та поле 2 на другому рівні.

Якщо цей синтаксис був використаний у python, є шанс сортувати field2 на першому рівні. З кортежем ризику немає.

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

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

Python використовує ключ, напрямок. Можна скористатися вищевказаним способом.

Тож у вашому випадку ви можете це зробити

for post in db.posts.find().sort('entities.user_mentions.screen_name',pymongo.ASCENDING):
        print post

0

TLDR: Агрегаційний конвеєр швидше порівняно зі звичайним .find().sort().

Тепер переходимо до реального пояснення. Існує два способи виконання операцій сортування в MongoDB:

  1. Використання .find()та .sort().
  2. Або використовуючи трубопровід агрегації.

Як вважають багато хто .find (). Sort () - найпростіший спосіб виконати сортування.

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

Однак це повільний процес порівняно з конвеєрним трубопроводом.

Перехід до методу трубопроводу агрегації. Етапи впровадження простого конвеєрного трубопроводу, призначеного для сортування, є:

  1. $ відповідність (необов'язковий крок)
  2. $ сортування

ПРИМІТКА: На мій досвід, конвеєрний конвеєр працює трохи швидше, ніж .find().sort()метод.

Ось приклад конвеєрного трубопроводу.

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

Спробуйте сам цей метод, порівняйте швидкість і дайте мені знати про це в коментарях.

Редагувати: Не забудьте використовувати allowDiskUse=Trueпід час сортування по кількох полях, інакше це призведе до помилки.


0

Скажімо, ви хочете сортувати за полем "created_on", тоді ви можете зробити так,

.sort('{}'.format('created_on'), 1 if sort_type == 'asc' else -1)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.