views:

392

answers:

2

I believe there is a bug in pymongo (or, at least, the documentation) which makes it impossible to run a findandupdate query.

Here's what happens. When I run:

    result = db.command({
        'findandmodify': 'my_collection',
        'query': {'foo': 'bar'},
        'update': {'$set': {'status': 'queued'}},
    })

The query that actually gets sent to the server is:

{ 'query': {'foo': 'bar'}, findandmodify: 'my_collection', … }

Note that the query argument is first, and findandmodify is second.

But this causes the server to throw up:

OperationFailure: command { 'query': {'foo': 'bar'}, findandmodify: 'my_collection', … } failed: no such cmd

Because the server expects findandmodify to be first (BSON dicts are, apparently, ordered).

Is there any work around for this?

+1  A: 

One workaround may be to construct the JavaScript version of the command and pass it to db.eval().

db.eval('db.runCommand({"findandmodify": "my_collection", "query": {"foo": "bar"}, "update": {"$set": {"status": "queued"}},})')

The issue is that, as Alex mentioned, Python dicts have no order, so you will need to build the string more-or-less manually.

Robert Kluin
Javascript objects have no intrinsic ordering either (by language standards, though specific JS implementations are of course free to add any arbitrary one -- point is, no guarantees about it!).
Alex Martelli
The jS standard says the order is undefined, but most implementations preserve the order you add elements to the object in. In either case, this example works correctly with Mongo's interpreter.
Robert Kluin
+3  A: 

For languages that don't have a built-in sorted dict type the mongo drivers include one. In python that is the SON type: http://api.mongodb.org/python/1.4%2B/api/pymongo/son.html. You will need to use that for all commands.

If that still fails make sure you are using the latest version of the database as findandmodify is a new feature.

mstearn
Ah, that looks like it'll work - thanks.
David Wolever