#python #mongodb #pymongo
#python #mongodb #pymongo
Вопрос:
Я пытаюсь использовать функцию сортировки при запросе моего 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, но это тоже не сработало. Кто-нибудь еще заставляет это работать или это ошибка.
Комментарии:
1. Как бы то ни было, в pymongo 3.12.1 больше нет
Connection
— возможно, было бы лучше использоватьMongoClient
в наши дни.
Ответ №1:
.sort()
в pymongo принимает key
и direction
в качестве параметров.
Итак, если вы хотите отсортировать, скажем, по id
, тогда вам следует .sort("_id", 1)
Для нескольких полей:
.sort([("field1", pymongo.ASCENDING), ("field2", pymongo.DESCENDING)])
Комментарии:
1.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
для сортировки нескольких полей.2. Для тех, кто ищет более подробную информацию, вот ссылка на документацию по сортировке с помощью pymongo api.mongodb.org/python/current/api/pymongo /…
3. ПРИМЕЧАНИЕ: по возрастанию: 1, по убыванию -1
4. Есть идеи, почему они вырезали такую простую нотацию JSON {«field1»: 1, «field2»: 1}?
5. @Nico — смотрите ответ romulomadu ниже
Ответ №2:
Вы можете попробовать это:
db.Account.find().sort("UserName")
db.Account.find().sort("UserName",pymongo.ASCENDING)
db.Account.find().sort("UserName",pymongo.DESCENDING)
Ответ №3:
Это тоже работает:
db.Account.find().sort('UserName', -1)
db.Account.find().sort('UserName', 1)
Я использую это в своем коде, пожалуйста, прокомментируйте, если я делаю что-то здесь не так, спасибо.
Комментарии:
1. Вы должны использовать:
ASCENDING
иDESCENDING
изpymongo
. 🙂
Ответ №4:
Почему python использует список кортежей вместо dict?
В python вы не можете гарантировать, что словарь будет интерпретирован в указанном вами порядке.
Итак, в оболочке mongo вы могли бы сделать .sort({'field1':1,'field2':1})
, и интерпретатор отсортировал бы поле 1 на первом уровне и поле 2 на втором уровне.
Если этот синтаксис использовался в python, есть вероятность сортировки по полю 2 на первом уровне. С tuple такого риска нет.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
Комментарии:
1. Просто добавлю к этому объяснение. Словарь по умолчанию не сохраняет порядок вставки, но вы всегда можете использовать OrderedDict, если требуется.
2. Начиная с Python 3.6 (в 2016 году), dict сохраняет порядок.
Ответ №5:
Сортировка по _id
убыванию:
collection.find(filter={"keyword": keyword}, sort=[( "_id", -1 )])
Сортировка по _id
возрастанию:
collection.find(filter={"keyword": keyword}, sort=[( "_id", 1 )])
Ответ №6:
DESC amp; ASC :
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]
doc = col.find().sort("name", -1) #
for x in doc:
print(x)
###################
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]
doc = col.find().sort("name", 1) #
for x in doc:
print(x)
Ответ №7:
TLDR: конвейер агрегации работает быстрее по сравнению с обычным .find().sort()
.
Теперь переходим к реальному объяснению. В MongoDB есть два способа выполнения операций сортировки:
- Используя
.find()
и.sort()
. - Или с помощью конвейера агрегации.
Как было предложено многими .find().sort() — это самый простой способ выполнить сортировку.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
Однако это медленный процесс по сравнению с конвейером агрегации.
Переходим к методу конвейера агрегации. Шаги по реализации простого конвейера агрегации, предназначенного для сортировки, следующие:
- $match (необязательный шаг)
- $сортировать
ПРИМЕЧАНИЕ: По моему опыту, конвейер агрегации работает немного быстрее, чем .find().sort()
метод.
Вот пример конвейера агрегации.
db.collection_name.aggregate([{
"$match": {
# your query - optional step
}
},
{
"$sort": {
"field_1": pymongo.ASCENDING,
"field_2": pymongo.DESCENDING,
....
}
}])
Попробуйте этот метод самостоятельно, сравните скорость и дайте мне знать об этом в комментариях.
Редактировать: Не забудьте использовать allowDiskUse=True
при сортировке по нескольким полям, иначе это выдаст ошибку.
Ответ №8:
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
Python использует ключ, направление. Вы можете использовать описанный выше способ.
Итак, в вашем случае вы можете сделать это
for post in db.posts.find().sort('entities.user_mentions.screen_name',pymongo.ASCENDING):
print post
Ответ №9:
Допустим, вы хотите выполнить сортировку по полю ‘created_on’, тогда вы можете сделать это следующим образом,
.sort('{}'.format('created_on'), 1 if sort_type == 'asc' else -1)
Комментарии:
1. Обычно удобнее использовать что-то вроде
pymongo.ASCENDING
иpymongo.DESCENDING
вместо чисел.