sorting in PyMongo

2,016 views
Skip to first unread message

aliane abdelouahab

unread,
Sep 4, 2012, 12:25:55 PM9/4/12
to mongodb-user
hi, sorry for this beginner question, but:
how to sort this:
produits = self.db.users.find_one({"email":email})["produit_up"]
produit_up is a nested document which has also a "date", "name"
attributes, so how do i use sorting using one of those attribute
i've used the method .sort() but it dont work, do i use
"produit_up.date" without specifying the ["produit_up"]?

Bernie Hackett

unread,
Sep 4, 2012, 12:31:52 PM9/4/12
to mongod...@googlegroups.com
The problem is you are calling find_one which returns a single
document (a python dict). sort() is a method of the Cursor class. You
get a cursor by calling Collection.find().

http://api.mongodb.org/python/current/api/pymongo/cursor.html#pymongo.cursor.Cursor.sort
> --
> You received this message because you are subscribed to the Google
> Groups "mongodb-user" group.
> To post to this group, send email to mongod...@googlegroups.com
> To unsubscribe from this group, send email to
> mongodb-user...@googlegroups.com
> See also the IRC channel -- freenode.net#mongodb

aliane abdelouahab

unread,
Sep 4, 2012, 12:33:57 PM9/4/12
to mongodb-user
ah ok, i'll try it, thank you :)

On 4 sep, 17:32, Bernie Hackett <ber...@10gen.com> wrote:
> The problem is you are calling find_one which returns a single
> document (a python dict). sort() is a method of the Cursor class. You
> get a cursor by calling Collection.find().
>
> http://api.mongodb.org/python/current/api/pymongo/cursor.html#pymongo...

aliane abdelouahab

unread,
Sep 4, 2012, 3:31:50 PM9/4/12
to mongodb-user
sorry but it dident work for nested documents, i dont know how to do
it

produits = self.db.users.find({"email":email}, {"produit_up":1, "_id":
0}).sort(("produit_up.namep"), pymongo.DESCENDING)

this dont work!

here is my schema:

user={
"pseudo":pseudo,
"email":email,
"avatar":avatar_id
"produit_up":{
"namep":namep,
"prix":prix,
}
}

everything worked without sorting, i just use produits =
self.db.users.find_one({"email":email})["produit_up"] and in my
templates i just call :

{% for produit in list(produits) %}
{{ produit["namep"] }}
{{ produit["prix"] }}
....
{% end %}

so how do i do the same if i use SORT and LIMIT.

Bernie Hackett

unread,
Sep 4, 2012, 4:09:23 PM9/4/12
to mongod...@googlegroups.com
> this dont work!

What doesn't work? Can you give me an example of what result you get
and what you are expecting?

Here's a simple example of how it should work:

# Without a limit
>>> cur = db.users.find({}, {"user": 1, "_id": 0}).sort("user.name", pymongo.DESCENDING)
>>> list(cur)
[{u'user': {u'name': u'ross'}}, {u'user': {u'name': u'jesse'}},
{u'user': {u'name': u'bernie'}}]
>>> cur = db.users.find({}, {"user": 1, "_id": 0}).sort("user.name", pymongo.ASCENDING)
>>> list(cur)
[{u'user': {u'name': u'bernie'}}, {u'user': {u'name': u'jesse'}},
{u'user': {u'name': u'ross'}}]

# With a limit.
>>> cur = db.users.find({}, {"user": 1, "_id": 0}).limit(1).sort("user.name", pymongo.DESCENDING)
>>> list(cur)
[{u'user': {u'name': u'ross'}}]
>>> cur = db.users.find({}, {"user": 1, "_id": 0}).limit(1).sort("user.name", pymongo.ASCENDING)
>>> list(cur)
[{u'user': {u'name': u'bernie'}}]

aliane abdelouahab

unread,
Sep 4, 2012, 5:13:52 PM9/4/12
to mongodb-user
ah ok, thank you, and the other question, if it's [{u'user': {u'name':
u'ross'}}, {u'user': {u'name': u'jesse'}}, {u'user': {u'name':
u'bernie'}}] then, how do i get the name of "jess" and loop there
using tornado (the same thing as for i in list do ....)

Bernie Hackett

unread,
Sep 4, 2012, 6:50:33 PM9/4/12
to mongod...@googlegroups.com
You can just iterate the cursor instead of converting to a list:

>>> cur = db.users.find({}, {"user": 1, "_id": 0}).sort("user.name", pymongo.ASCENDING)
>>> for doc in cur:
... if doc['user']['name'] == 'jesse':
... doc
...
{u'user': {u'name': u'jesse'}}


aliane abdelouahab

unread,
Sep 5, 2012, 12:20:31 PM9/5/12
to mongodb-user
ah! thank you :)
and sorry again ;)

aliane abdelouahab

unread,
Sep 5, 2012, 5:33:33 PM9/5/12
to mongodb-user
am sorry but i dont work!

list(db.users.find({"pseudo":"alucaard"}, {"produit_up":
1}).sort("produit_up.prix", pymongo.DESCENDING))
Out[1]:
[{u'_id': ObjectId('50479ed63a5f3a0a94db69d7'),
u'produit_up': [{u'date': u'2012-09-05',
u'description': u'portable samsung coulissant tr\xe8s bon \xe9tat
avec carte m\xe9moire 2 giga',
u'namep': u'samsung e250',
u'photo': u'504609253a5f3a07fc13071a',
u'prix': 5000,
u'vendu': False},
{u'date': u'2012-09-05',
u'description': u'nokia 3310 tr\xe8s solide, tr\xe8s bon \xe9tat
\xe0 saisir',
u'namep': u'nokia 3310',
u'photo': u'504609253a5f3a07fc13071a',
u'prix': 1000,
u'vendu': False}]}]
list(db.users.find({"pseudo":"alucaard"}, {"produit_up":
1}).sort("produit_up.prix", pymongo.ASCENDING))
Out[1]:
[{u'_id': ObjectId('50479ed63a5f3a0a94db69d7'),
u'produit_up': [{u'date': u'2012-09-05',
u'description': u'portable samsung coulissant tr\xe8s bon \xe9tat
avec carte m\xe9moire 2 giga',
u'namep': u'samsung e250',
u'photo': u'504609253a5f3a07fc13071a',
u'prix': 5000,
u'vendu': False},
{u'date': u'2012-09-05',
u'description': u'nokia 3310 tr\xe8s solide, tr\xe8s bon \xe9tat
\xe0 saisir',
u'namep': u'nokia 3310',
u'photo': u'504609253a5f3a07fc13071a',
u'prix': 1000,
u'vendu': False}]}]

it always give me the same result! i've even entered a falsy parameter
(a key that dont exist) and it gives the result! so it's like the
"produit_up.prix" dont exist!

Bernie Hackett

unread,
Sep 5, 2012, 7:59:21 PM9/5/12
to mongod...@googlegroups.com
Ah, I understand now. The sort won't affect the order of the
subdocuments in your 'produit_up' array. It only affects the order the
result documents are returned in (in this example you are only
returning one document so there is nothing to sort). If you need the
'produit_up' array to be sorted you have to do that client side.
MongoDB won't do that for you.

Thomas Rueckstiess

unread,
Sep 6, 2012, 3:18:18 AM9/6/12
to mongod...@googlegroups.com
If you're running MongoDB version 2.2 you can use the aggregation framework to sort the subdocuments.

The call in the mongo shell would look like this:

db.produits.aggregate(
    {$match: {'email': email}}, 
    {$project : { 'produit_up' : 1 }}, 
    {$unwind : '$produit_up' }, 
    {$sort: {'produit_up.prix': -1}}, 
    {$group: {'_id': '$_id', 'produit_up':{$push: '$produit_up'}}}
)

Explanation: the $match is the query to find the document by email. $project selects only the produit_up array to be included in the result. $unwind will create documents for each element of the array in produit_up. Then we can sort them by prix, either ascending (1) or descending (-1), and finally we $group the results back together (the opposite of the $unwind).

You may have to adapt the example to match the pymongo call.

aliane abdelouahab

unread,
Sep 6, 2012, 10:09:22 AM9/6/12
to mongodb-user
ah! so i cant do it directly!
thank you :)

aliane abdelouahab

unread,
Sep 6, 2012, 10:10:10 AM9/6/12
to mongodb-user
ah! so i've a chance to learn mongodb just when it reachs 2.2 :D
else i should use map reduce :D
thank you :)

On 6 sep, 08:18, Thomas Rueckstiess <Thomas.Ruecksti...@10gen.com>
wrote:
> > > To post to this group, send email to mongod...@googlegroups.com<javascript:>
> > > To unsubscribe from this group, send email to
> > > mongodb-user...@googlegroups.com <javascript:>

aliane abdelouahab

unread,
Sep 7, 2012, 10:07:31 AM9/7/12
to mongodb-user
am sorry but it dident work
it give me errors!
in mongo shell it give me error (near id) and in pymongo when using
the "" whith $.. it give me errors too
any ideas?

A. Jesse Jiryu Davis

unread,
Sep 7, 2012, 10:55:26 AM9/7/12
to mongod...@googlegroups.com
Aliane, you need to post the exact command you issued to MongoDB and then post the exact error that Mongo reported, otherwise we can't help.

However, I recommend that you simply sort the array in Python, not with an aggregate command. Sorting in Python is simpler and faster and will put much less burden on the database server.

aliane abdelouahab

unread,
Sep 7, 2012, 12:04:32 PM9/7/12
to mongodb-user
am sorry, i'll upload the code, am not on the machine where the is the
code.
i'll try to sort using python and post the result.
thank you :)

aliane abdelouahab

unread,
Sep 7, 2012, 5:42:21 PM9/7/12
to mongodb-user
solved.
thank you again :)
here is the link of stackoverflow
http://stackoverflow.com/questions/12322975/sorting-a-list-of-dictionnaries-using-a-key
Reply all
Reply to author
Forward
0 new messages