2014-06-18 63 views
0

的pymongo documentation說:Pymongo返回沒有成功更新後/刪除操作

默認情況下,從該 更新成功,提高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 ,u'err ':無,u'connectionId':12037,u'n ':1, u'updatedExisting':真,u'lastOp':時間戳(1403099751,1)}

當我手動檢查數據庫,我發現它已從friend_list中拉出名稱。現在,如果我同再次運行IE瀏覽器試圖拉它不存在friend_list一個名字:

{u'ok ':1.0,u'err':無,u'connectionId「:12037,u'n ':1, u'updatedExisting':真,u'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)} 
>>> 

最後一條語句試圖從列表中刪除項目,即使該項目不再在列表中存在。

回答

1

您正在混合這些條款。您突出顯示的文檔部分是指寫入確認,而不是更新文檔的數量。

簡而言之,當驅動程序向MongoDB發送寫入命令並且您有默認的寫入確認(w=1)時,如果MongoDB未確認更新完成成功,驅動程序將拋出OperationFailure錯誤。您可以在MongoDB pages上閱讀更多關於它的詳細信息。

這兩個更新實際上都是成功的(MongoDB確認已應用更新)。這就是爲什麼你沒有得到一個錯誤。你的問題是你的更新查詢並沒有實際更新任何文檔。

如果您在MongoDB的外殼V2.6 +,在沒有文件實際上是修改的更新,你會得到這樣的結果:

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

而結果爲實際上改變了更新文件將是這樣的:

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

編輯:

我用pymongo上安裝的舊版本(2.6.3) Ubuntu與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}}) 

EDIT2

那是因爲你正在使用MongoDB的2.4。如果您在MongoHQ上使用沙箱/免費版本,則目前無法更改(link)。

MongoDB 2.6正在返回updatedExisting字段中的更新命令的響應(這是對你很重要的一個)。我懷疑這是因爲以V 2.6的變化寫入協議:

用於寫入操作的新協議集成寫與 寫操作的擔憂,消除了對單獨GetLastError函數 命令的需要。寫入方法現在返回寫入操作的狀態,包括錯誤信息,即 。

+0

是Pymongo或我的代碼中的錯誤是錯誤的嗎? – avi

+0

@avi更新了我的答案 –

+0

我已經更新了這個問題。如果你在同一個文件上做另一個'pull',那麼響應是一樣的。 – avi

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)} 
+0

^我已更新問題。如果你在同一個文件上做另一個'pull',那麼響應是一樣的。 – avi