【问题标题】:Pymongo returns none after successful update/remove operations成功更新/删除操作后 Pymongo 不返回任何内容
【发布时间】:2014-06-19 16:38:46
【问题描述】:

pymongo documentation 说:

默认情况下,服务器会请求确认 更新成功,如果发生错误,将引发 OperationFailure

我正在使用 Pymongo 2.7.1 和 Python 2.7.5。以下操作返回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, u'err': 无, u'connectionId': 12037, u'n': 1, u'updatedExisting': True, u'lastOp': Timestamp(1403099751, 1)}

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

{u'ok': 1.0, u'err': 无, u'connectionId': 12037, u'n': 1, u'updatedExisting': True, u'lastOp': Timestamp(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)}
>>>

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

【问题讨论】:

    标签: python mongodb pymongo


    【解决方案1】:

    您混淆了条款。您突出显示的文档部分是指写确认而不是更新的文档数。

    简而言之,当驱动程序向 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 })
    

    编辑:

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

    我删除了 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}})
    

    编辑2

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

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

    一种新的写操作协议将写关注点与 写操作,无需单独的 getLastError 命令。写方法现在返回写操作的状态, 包括错误信息。

    【讨论】:

    • 但是nok 在这方面是什么意思:{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
    • @SaadRehmanShah ok: 1 表示操作完成且没有错误,n: 1 报告更新操作匹配的文档数
    【解决方案2】:

    我假设您使用的是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)}
    

    【讨论】:

    • ^我已经更新了这个问题。如果您在同一个文档上执行另一个pull,则响应相同。
    猜你喜欢
    • 2021-03-14
    • 2015-12-13
    • 2021-09-29
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 2011-02-14
    • 2012-12-28
    • 1970-01-01
    相关资源
    最近更新 更多