2012-10-23 45 views
15

我是MongoDB和Backbone的新手,所以我試圖理解它們,但它很難。我有一個很大的問題:我無法理解如何操作Backbone.Model中的屬性以便在視圖中使用我所需要的。更具體的 - 我有一個模式MongoError:無法更改文檔的_id

window.User = Backbone.Model.extend({ 

    urlRoot:"/user", 
    idAttribute: "_id", 

    defaults: { 
     _id: null, 
     name: "", 
     email: "[email protected]" 
    } 
}); 

window.UserCollection = Backbone.Collection.extend({ 
    model: User, 

    url: "user/:id" 
}); 

而且我有一個查看

beforeSave: function(){ 
    var self = this; 
    var check = this.model.validateAll(); 
    if (check.isValid === false) { 
     utils.displayValidationErrors(check.messages); 
     return false; 
    } 
    this.saveUser(); 
    return false; 
}, 

saveUser: function(){ 
    var self = this; 
    console.log('before save'); 
    this.model.save(null, { 
     success: function(model){ 
      self.render(); 
      app.navigate('user/' + model.id, false); 
      utils.showAlert('Success!', 'User saved successfully', 'alert-success'); 
     }, 
     error: function(){ 
      utils.showAlert('Error', 'An error occurred while trying to save this item', 'alert-error'); 
     } 
    }); 
} 

我不得不使用從除「_id」任何領域「放」的方法白衣數據,所以它必須是水木清華這樣的:

{"name": "Foo", "email": "[email protected]"} 

但每一次,不取決於我做什麼它發送

{**"_id": "5083e4a7f4c0c4e270000001"**, "name": "Foo", "email": "[email protected]"} 

,並從服務器這個錯誤:

MongoError: cannot change _id of a document old:{ _id: ObjectId('5083e4a7f4c0c4e270000001'), name: "Foo" } new:{ _id: "5083e4a7f4c0c4e270000001", name: "Bar", email: "[email protected]" }

Github上鍊接:https://github.com/pruntoff/habo

提前感謝!

+0

當你調用'model.save()'是一個後正在執行或PUT? – InPursuit

+0

它被執行。 'app.get('/ user /:id',usr.findById); app.put('/ user /:id',usr.updateUser);' – Pruntoff

+0

如果骨幹在你調用'save'時做了PUT,那麼模型的idAttribute(你的情況下是_id)不應該被髮送。你可以在'save()'之前在模型上調用'isNew()'並驗證它是否返回'false'?在調用save()之前,請確認'this.model.id'不爲空或未定義。 – InPursuit

回答

6

從看你的mongo錯誤,問題不在於mongo,它只是在做它應該做的事情。它有一個帶有ObjectId類型的_id的對象:ObjectId('xxx'),現在你試圖改變該對象,使其具有String類型的_id(_id:「5083e4a7f4c0c4e270000001」),並且Mongo顯然不喜歡。

所以,問題是:爲什麼對象有一個ObjectId類型的ID在第一個地方?你是如何第一次設定它的?如果你使用其他方法來初始化它(我猜服務器端),你應該將id類型設置爲一個String,以便它與來自腳本庫的類型相同。如果你想讓它保留一個ObjectId,你需要將來自腳本的String轉換爲ObjectId,然後將它保存到Mongo中。

HTH。

+0

非常感謝您的回答! 我看到這個問題,但在MongoDB中也存在問題,如果我理解正確,mongo docs說:* _id字段是不可變的。如果你試圖在更新上改變它的值,你會在getLastError中得到一個「Mod on _id not allowed」的錯誤。*所以我認爲我必須解除發送模型中的_id attr,但模型需要它。 總之,你能告訴我,如何將字符串轉換爲ObjectId對象,當我在模型中繪製JSON數據?大小寫請求到服務器有_id字符串的JSON對象,我不能在服務器端操縱它。 – Pruntoff

+0

我認爲可以在更新時發送該字段,但作爲標識符來查找要更改的對象。我有一種感覺,如果你以同樣的格式發送id(ObjectId),Mongo不會反對(因爲它沒有被改變)。我不知道如何將字符串轉換爲ObjectId,因爲我不知道你在用什麼語言,但問題仍然存在:它是如何獲得ObjectId的?原始對象從哪裏來? – TheZuck

+0

我解決了這個問題,你說得對,這完全是關於格式化。 回答你的問題:當我插入一些JSON數據時,ObjectId首先被mongoDb自動獲取。 爲了解決這個問題,我不需要使用mongoDB和mongoose來代替monodDB驅動程序,我使用'.Types.ObjectId;'。如果我沒有錯誤mongo驅動程序沒有方法將數據轉換爲ObjectId數據。 :(非常感謝您的幫助! – Pruntoff

5

MongoDB 創建 _id作爲ObjectID,但不檢索 _id作爲ObjectID。

無論這種不一致性是否爲「正確行爲」,對於大多數MongoDB用戶來說,這無疑是一個令人討厭的驚喜。

你可以解決它:

if (this._id && (typeof(this._id) === 'string')) { 
    log('Fixing id') 
    this._id = mongodb.ObjectID.createFromHexString(this._id) 
} 

MongoDB can't update document because _id is string, not ObjectId

+1

或者,您可以定義'var BSON = mongodb.BSONPure'並使用此函數:'this._id = new BSON.ObjectID(this._id);' –