2013-05-27 37 views
0

我試圖瞭解使用PHP與mongodb 2.4.3 win32的奇怪行爲。 我嘗試讓服務器端生成序列ID。在插入槽中使用的存儲函數PHP運行多次

當使用存儲函數作爲參數之一插入文檔時,似乎存儲的函數在每次插入時被調用多次。

比方說,我有這樣的初始化的計數器:

db.counters.insert({ _id: "uqid", seq: NumberLong(0) }); 

我點名getUqid存儲功能。當我這樣做,其定義爲

db.system.js.save( 
    { _id: "getUqid", 
     value: function() { 
        var ret = db.counters.findAndModify(
        { query: { _id: "uqid" }, 
        update: { $inc: { seq: NumberLong(1) } }, 
        new: true 
        }); 
        return ret.seq; 
        } 
      } ); 

3個插入這樣的:

$conn->test->ads->insert(['qid' => new MongoCode('getUqid()') , 'name' => "Sarah C."]); 

我得到這樣的東西:

db.ads.find() 
{ "_id" : ObjectId("51a34f8bf0774cac03000000"), "qid" : 17, "name" : "Sarah C." } 
{ "_id" : ObjectId("51a34f8bf0774cac03000001"), "qid" : 20, "name" : "Michel D." } 
{ "_id" : ObjectId("51a34f8bf0774cac03000002"), "qid" : 23, "name" : "Robert U." } 

任何線索爲什麼qid正在步入3?這應該意味着我收到了三個電話給我存儲的功能嗎?

在此先感謝您的幫助,關心。

PS:第二個問題:NumberLong仍然需要確定我們在內部mongodb存儲中有64位無符號整數嗎?任何命令都要在shell中進行交叉檢查?

+0

首先,你爲什麼不在PHP中查找和修改?你也可能得到這個,因爲你在插入一個函數的時候評估一個函數,結果是在MongoDB中導致某種雙重運行。存儲的功能,從來不應該這樣使用 – Sammaye

+0

嗨,1)我想只插入一個動作,如果可能的話當然。 2)我嘗試模仿這個[create-an-auto-incrementing-field](http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/),「官方」mongoDB建議做自動遞增序列號,但直接從PHP。我沒有正確理解這個嗎? –

+0

不,getNextSequence()應該是一個PHP函數,然後使用findandmodify。使用JS是因爲這是shell語言 – Sammaye

回答

1

PHP-841交叉引用此問題。從PHP的角度來看,你實際上在qid字段中存儲了一個BSON code value。使用mongodump命令可能會驗證從數據庫中獲取結果或執行數據庫導出時的情況。

問題在於JS shell在顯示時錯誤地評估了代碼類型,這就是執行findAndModify的地步。此修補程序應包含在隨後的服務器版本中。

與此同時,Sammaye建議從PHP調用findAndModify是這類功能的最佳選擇。巧合的是,它也是在MongoDB ODM原則中所做的(請參閱:IncrementGenerator)。它需要額外往返服務器,但這是必要的,因爲MongoDB在寫操作期間沒有執行JS回調的功能。

如果最小化向MongoDB的往返是至關重要的,那麼可以通過執行服務器端JS通過PHP執行MongoDB::execute()來插入文檔,並執行諸如返回生成的ID作爲命令響應的操作。當然,這通常不是可取的,JS評估有其自己的警告。