Frage

I'm trying to perfom update on mongodb, using motor and tornadoweb with the following code:

@gen.coroutine
def set_project_status(self, pid, status):
    try:
        project = yield motor.Op(self.db[S.DB_PROJECT_TABLE].find_one, {'PID': pid})
        logging.debug('set_project_status old_id {0}'.format(project['_id']))

        project_update = yield motor.Op(self.db[S.DB_PROJECT_TABLE].update,
                           {'_id': ObjectId(project['_id'])}, {'STATUS': status})

        logging.debug('set_project_status saving')
        save = yield motor.Op(self.db[S.DB_PROJECT_TABLE].save, project_update)
        logging.debug('set_project_status saved {0}'.format(save))

        logging.debug('set_project_status saved id {0}'.format(project_update))

        project = yield motor.Op(self.db[S.DB_PROJECT_TABLE].find_one, {'PID': pid})
        logging.debug('set_project_status project {0}'.format(project))

        raise gen.Return(True)

    except Exception,e:
        logging.debug('{0} {1} {2}'.format(pid, status, e))
        raise gen.Return(False)

What I get in logs is:

set_project_status old_id 52d532d4b12c6478ce767a83
set_project_status saving
set_project_status saved 52d532d4b12c6478ce767a84
set_project_status saved id {u'ok': 1.0, u'err': None, u'connectionId': 2052, u'n': 1, u'updatedExisting': True, '_id': ObjectId('52d532d4b12c6478ce767a84')}
set_project_status project None

I'm getting some intermediate object (u'updatedExisting ?) and None later on.

I seems, like I should do some 'commit'or so. Any ideas?

Greets!

War es hilfreich?

Lösung

Just do this:

@gen.coroutine
def set_project_status(self, pid, status):
    try:
        result = yield motor.Op(self.db[S.DB_PROJECT_TABLE].update,
                       {'PID': pid}, {'$set': {'STATUS': status}})

        logging.debug('update result: {0}'.format(result))        
        project = yield motor.Op(self.db[S.DB_PROJECT_TABLE].find_one, {'PID': pid})
        logging.debug('set_project_status project {0}'.format(project))
    except Exception,e:
        logging.debug('{0} {1} {2}'.format(pid, status, e))
        raise gen.Return(False)

See the docs for "update".

First, you want to use $set to update a single field in the document. Your update code replaces the whole document with only {'STATUS': status}, deleting any other fields. The code I show just sets the 'STATUS' field and leaves the rest of the document untouched. Also, if project['_id'] is already an ObjectId, calling ObjectId() on it has no effect; it's unnecessary.

You don't need to find the document, then update it, then save it. Just issue an "update". The document is immediately updated in MongoDB.

The return value of 'update' is not the updated document. The return value is some information about the operation, such as 'updatedExisting' and 'n'.

In the code I showed, you find the document after updating it, so you can see the effect of the update. But that's unnecessary, too; you should delete the call to find_one once you have this working. I'd simply check that result.get('n') == 1 and then return True.

(And finally, just to check: you have a unique index on 'PID', right?)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top