2017-05-29 54 views
1

我通過兩個模型和鑑別密鑰(簡單的例子)表示在貓鼬類層次: 更改鑑別值/受歧視貓鼬類

var options = {discriminatorKey: 'kind'}; 
var UserSchema = new mongoose.Schema({ 
    username: {type: String, index: true}, 
    // some other fields 
}, options); 

// some schema methods 

var User = mongoose.model('User', UserSchema); 
var PowerUserSchema = new mongoose.Schema({ 
    username: {type: String, index: true}, 
    // some other fields 
    rank: {type: String} 
}, options); 
var PowerUser = User.discriminator('PowerUser', PowerUserSchema); 

到目前爲止,這工作得很好,但是我跑進在這種情況下,我想將用戶推廣到PowerUser。我最初的想法是設置一個用戶的「種」屬性和調用save()上的實例,希望一旦值被檢索接下來的時間,正確的貓鼬類將返回:

var user = ... // retrieve user 
user.kind = 'PowerUser'; 
user.save(); 
user = ... // retrieve user again 

這並未看起來不起作用,因爲「kind」值不會保存到實例中。我遇到了this建議,不幸的是,它並沒有更新鑑別器的值。

我現在的問題是:我是否在正確的軌道上?是否更新了鑑別器值,甚至允許這樣的情況,還是應該以不同的方式更好地構造我的數據(例如,對於兩者都使用單一模式,用「類型」條目指定每個實例是什麼;這會產生效果對於降級情況,沒有信息丟失。)

此外,pro(de)moting用戶不應該打破我的數據庫中(Power)用戶被引用的所有實例。

謝謝!

+0

存在你爲什麼不添加角色數組給每個用戶,然後添加和刪除隨你便? –

+0

所以你「可以」做到這一點,但只是修改數據中的鑑別器值聽起來不是很符合OOP。據推測'PowerUser'具有不同的屬性和可能的​​「驗證規則」或至少一些區分的「所需」數據。因此,將對象「強制」爲「PowerUser」並保存它可能更「正確」。 –

+0

而*「很遺憾沒有更新」*,因爲您沒有**閱讀**引用的問題。如果你看看帖子,你會看到'{discriminatorKey:'kind'}'被傳遞給Schema選項。這意味着該鍵的「默認」值被覆蓋。這就是爲什麼後面的建議是設置'.kind'屬性。通過「默認」,鑑別器關鍵字的屬性被命名爲「__t」。因此'user .__ t =「PowerUser」'。但就像我說的,哈克! –

回答

0

最終我得到了這個做的工作:

var user = ... // retrieve user 
var powerUser = PowerUser.hydrate(user.toObject()); 
powerUser.kind = 'PowerUser'; 
powerUser.save(); 
powerUser = ... // retrieve user again 

在一個側面說明,降級高級用戶返回到用戶似乎沒有奏效的方式。

+0

它可能無法按預期工作。如果'user'和'powerUser'具有它們自己的屬性,那麼在轉換之後,'user'的舊屬性仍然設置在新的'powerUser'中。它必須是一個錯誤。 –

0

有使用findOneAndUpdate你試過模型

User.findOneAndUpdate({_id: _user._id}, {$set: {kind: "PowerUser"}, {new: true}, function (err, doc) { 
     should.not.exist(err); 
     should.exist(doc.kind); 
     doc.kind.should.equal('PowerUser'); 

     done(); 
     }); 

,你可以在情況下,你還需要刪除已經設置屬性使用一個靜態的方法是這樣的。新價值:真實是讓新修改的文​​件和嚴格的:假的,所以你可以在不取消設置已經在值UserSchema

changes = {kind: "PowerUser"} 

UserSchema.statics.switchKind = function (id, changes, callBack) { 
    const unset = { 
    rank: undefined, 
    someOtherField: undefined 
    }; 
    return this.findOneAndUpdate({_id: id}, {$set: changes, $unset: unset}, {new: true, strict: false}, callBack); 
};