2012-04-19 114 views
3

我在Node中創建了一個具有一些CRUD組件的應用程序。在我的其中一個數據對象中,我有一個save()方法,用於在對象具有在集合中找到的ID時更新記錄,或者如果沒有,則插入新文檔。另外,如果做一個upsert,我想回到Mongo生成的文檔的_id。MongoDB findAndModify()添加查詢更新子句

看來findAndModify會這樣做,實際上,它確實從數據庫返回一個_id值。在我的查詢子句中,我通過_id進行過濾。如果我的數據對象沒有id,Mongo會正確地做一個upsert,不過,無論它返回什麼_id值,除了我在update子句中設置的鍵之外,它還會在基於文檔的基礎上設置_id我在query條款中使用了什麼值。爲清楚起見,某些代碼:

User.prototype.save = function(callback) { 
    var that = this; 

    var args = { 
     'query'  : { _id: this.getId() }, //getId() returns empty string if not set 
     'update' : { $set : { 
      firstName : this.firstName, 
      lastName : this.lastName, 
      email  : this.email 
      //_id  : this.getId() 
      // which is blank, is magically getting added due to query clause 
     }}, 
     'new'  : true, 
     'upsert' : true, 
     'fields' : {'_id' : true} 
    }; 

    this.db.collection(dbName).findAndModify(args, function(err, doc){ 
     if(!that.getId()) { 
      that.setId(doc._id); 
     } 

     if (typeof(callback) === "function"){ 
      callback.call(that); 
     } 
    }); 
} 

我只是在尋找更新的語義也恰好在UPSERT返回蒙戈生成的_id。我不希望query子句的值額外追加,就好像它們在update映射中一樣。有什麼辦法可以實現我的目標?

回答

2

您可以生成_id客戶端和新的new require('mongodb').ObjectID() 然後,您可以執行常規的upsert(無需執行findandmodify),因爲您已經擁有_id。但是,如果您使用的是findAndModify,請記住節點驅動程序在位置上接受此函數的參數,而不是作爲對象(如在常規的mongo shell中)。 與節點司機做findandmodify正確的格式如下:

collection.findAndModify(criteria, sort, update[, options, callback])

(選項和回調是可選的PARAMS)。全文檔在這裏: https://github.com/mongodb/node-mongodb-native/blob/master/docs/insert.md

+0

我實際上使用MongoJS,它是本地Mongo驅動程序的包裝,它似乎接受對象語法。但是,關於生成身份證客戶端的觀點似乎是最好的解決方案。 我仍然想知道爲什麼在查詢子句中的條件既被評估,又被添加到upsert中的記錄中。 – DuxPrime 2012-04-19 16:35:47

+1

@DuxPrime這是設計 - 如果您提供非空查詢,「插入」意味着如果沒有文檔匹配該查詢,則它必須創建一個 - 因此它會被添加到正在創建的記錄中。 – mpobrien 2012-04-19 17:58:27

+1

以下應該工作... _id:this.getId()||新的mongodb.ObjectID() – Tracker1 2012-07-27 23:20:00