Como classificar mongodb com pymongo

164

Estou tentando usar o recurso de classificação ao consultar meu mongoDB, mas está falhando. A mesma consulta funciona no console do MongoDB, mas não aqui. O código é o seguinte:

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

O erro que recebo é o seguinte:

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

Encontrei um link em outro lugar que diz que preciso colocar um 'u' na frente da chave se estiver usando o pymongo, mas isso também não funcionou. Qualquer outra pessoa faz isso funcionar ou é um bug.

WildBill
fonte

Respostas:

302

.sort(), no pymongo, toma keye directioncomo parâmetros.

Então, se você quiser classificar, digamos, identão você deve.sort("_id", 1)

Para vários campos:

.sort([("field1", pymongo.ASCENDING), ("field2", pymongo.DESCENDING)])
Ben
fonte
124
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])para classificar vários campos.
Richardr
4
Para quem procura mais detalhes, aqui está um link para a documentação sobre classificação com pymongo api.mongodb.org/python/current/api/pymongo/…
Shane Reustle
21
NOTA: ascendente: 1, descendente -1
Martlark 6/15
2
Alguma idéia de por que eles massacraram a notação JSON tão fácil {"field1": 1, "field2": 1}?
Nico
2
@Nico - ver resposta romulomadu abaixo
Bajal
34

Você pode tentar isso:

db.Account.find().sort("UserName")  
db.Account.find().sort("UserName",pymongo.ASCENDING)   
db.Account.find().sort("UserName",pymongo.DESCENDING)  
nova Luz
fonte
17

Isso também funciona:

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

Estou usando isso no meu código, por favor, comente se estou fazendo algo errado aqui, obrigado.

Snehal Parmar
fonte
Você deve usar: ASCENDINGe DESCENDINGde pymongo. :)
Sn0pY
7

Por que python usa a lista de tuplas em vez de ditar?

No python, você não pode garantir que o dicionário seja interpretado na ordem que você declarou.

Portanto, no mongo shell você pode fazer .sort({'field1':1,'field2':1})e o intérprete deve classificar o campo1 no primeiro nível e o campo 2 no segundo nível.

Se essa sintaxe foi usada em python, há uma chance de classificar o field2 no primeiro nível. Com tupla, não há risco.

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

Python usa chave, direção. Você pode usar o caminho acima.

Então, no seu caso, você pode fazer isso

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

TLDR: o pipeline de agregação é mais rápido em comparação com o convencional .find().sort().

Agora vamos para a explicação real. Há duas maneiras de executar operações de classificação no MongoDB:

  1. Usando .find()e .sort().
  2. Ou usando o pipeline de agregação.

Conforme sugerido por muitos .find (). Sort () é a maneira mais simples de realizar a classificação.

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

No entanto, esse é um processo lento comparado ao pipeline de agregação.

Chegando ao método de agregação de pipeline. As etapas para implementar o pipeline de agregação simples destinado à classificação são:

  1. $ match (etapa opcional)
  2. $ sort

NOTA: Na minha experiência, o pipeline de agregação funciona um pouco mais rápido que o .find().sort()método.

Aqui está um exemplo do pipeline de agregação.

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

Tente você mesmo esse método, compare a velocidade e deixe-me saber sobre isso nos comentários.

Editar: Não se esqueça de usar allowDiskUse=Trueao classificar em vários campos, caso contrário, ocorrerá um erro.

Anuj Gupta
fonte
0

Digamos que você queira classificar por campo 'created_on', para fazer assim,

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