成功更新/删除操作后,Pymongo不返回任何内容

时间:2014-06-18 14:00:45

标签: python mongodb pymongo

pymongo documentation说:

  

默认情况下,从服务器请求确认   更新成功,如果发生错误则提升OperationFailure

我在Python 2.7.5中使用Pymongo 2.7.1。以下操作返回None,操作是否成功:

user_db.update({'email_id': user_email}, {'$pull': {'friend_list': existing_friend}})
user_db.update({'email_id': user_email}, {'$pull': {'friend_list': non_existing_friend}})

在第二个声明中,我试图提取friend_list中不存在的内容。

remove同样如此。它也会返回None,操作成功或不成功,即是否删除了文档:

user_db.remove({'name': 'john'}

我通过w=1并收到以下回复:

  

{u' ok':1.0,你'错误':没有,你' connectionId':12037,你' n':1,   u' updatedExisting':是的,你' lastOp':时间戳(1403099751,1)}

当我手动检查数据库时,我发现它已从friend_list中取出名称。现在,如果我再次运行相同,即尝试提取friend_list中不存在的名称:

  

{u' ok':1.0,你'错误':没有,你' connectionId':12037,你' n':1,   u' updatedExisting':是的,你' lastOp':时间戳(1403099873,1)}

与之前相同。

那我怎么知道更新和删除操作是否成功?

编辑:正如答案所指出的,我使用的是连接而不是MongoClient。现在我已经更新,remove正在运行。但update无法正常运行:

>>> conn = pymongo.MongoClient(MONGOHQ_URL)
>>> db = conn['test']
>>> test_collection = db.test
>>>
>>> test_collection.insert({'name': 'john'})
ObjectId('53a25612a760360253920619')
>>>  
>>> test_collection.update({'name': 'john'}, {'$addToSet': {'friends': 'merry'}})
{u'ok': 1.0, u'err': None, u'connectionId': 12317, u'n': 1, u'updatedExisting': True, u'lastOp': Timestamp(1403147936, 1)}
>>> 
>>> test_collection.update({'name': 'john'}, {'$pull': {'friends': 'merry'}})
{u'ok': 1.0, u'err': None, u'connectionId': 12317, u'n': 1, u'updatedExisting': True, u'lastOp': Timestamp(1403147959, 1)}
>>> 
>>> test_collection.update({'name': 'john'}, {'$pull': {'friends': 'merry'}})
{u'ok': 1.0, u'err': None, u'connectionId': 12317, u'n': 1, u'updatedExisting': True, u'lastOp': Timestamp(1403147963, 1)}
>>>

最后一条语句是尝试从列表中删除项目,即使该项目不再存在于列表中。

2 个答案:

答案 0 :(得分:2)

你正在混合这些条款。您突出显示的文档部分是指写入确认而不是更新的文档数。

简而言之,当驱动程序向MongoDB发送写入命令并且您具有默认写入确认(w=1)时,如果MongoDB未确认更新已完成,则驱动程序将抛出OperationFailure错误成功的。您可以在MongoDB pages上阅读有关它的更多详细信息。

您的两次更新实际上都是成功的(MongoDB确认已应用更新)。这就是你没有得到错误的原因。您的问题是您的更新查询实际上没有更新任何文档。

如果你在MongoDB shell v2.6 +中进行了更新,没有实际修改过文档,你会得到如下结果:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

实际更改文档的更新结果如下所示:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

修改:

我使用的是带有apt-get的Ubuntu上安装的较旧版本的pymongo(2.6.3),我得到的更新查询的响应与你得到的相同。

我删除了python-pymongo包并使用pip更新到最新版本的pymongo。我从修改文档的更新中得到以下响应:

{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}

我在MongoDB 2.6上测试了这个。使用此代码。

from pymongo import MongoClient

m = MongoClient('localhost', 27017)

db = m.test

print db.test.update({}, {'$pull': {'a'  : 1}})

<强> EDIT2

那是因为你使用的是MongoDB 2.4。如果您在MongoHQ上使用沙盒/免费版本,则目前无法更改(link)。

MongoDB 2.6在更新命令的响应中返回updatedExisting字段(这对您来说非常重要)。我怀疑那是因为v 2.6中改变了写协议:

  

用于写入操作的新协议将写入问题集成到   写操作,不需要单独的getLastError   命令。 Write方法现在返回写操作的状态,   包括错误信息。

答案 1 :(得分:0)

我假设您正在使用pymongo.Connection,默认情况下会对MongoDB执行未确认的写入操作。因此Connection不会告诉您更新操作的结果。

不推荐连接;你应该使用pymongo.MongoClient代替。 MongoClient有许多优点,包括它默认确认写入。如果您使用MongoClient,您将获得有关每次更新的信息:

>>> import pymongo
>>> collection = pymongo.MongoClient().test.collection
>>> collection.insert({'_id': 1, 'array': ['a']})
1
>>> collection.update({'_id': 1}, {'$pull': {'array': 'a'}})
{u'nModified': 1, u'ok': 1, u'n': 1, 'updatedExisting': True, u'electionId': ObjectId('53a1a6bd30492fdb9fb5610a'), u'lastOp': Timestamp(1403111261, 1)}