MongoDB的。 如何更新数组内的json属性

我正在使用平均值堆栈。 我对此感到不舒服,并且陷入了一片腌制。 我见过使用set或push更新logging的例子,但是因为我试图更新一个json对象内的一个json对象,所以我遇到了麻烦。

考虑下面的模式

token: { type: String, required: "FB access token required." }, fbId: { type: String, required: "FB id required.", unique: true }, accounts: { type: Array, default: [] } 

我的帐户数组由json对象组成,每个对象如下所示:

 { "name": "some name", "credentials": { "username": "some username", "password": "some password" } 

每次用户添加新帐户时,我都会尝试更新帐户。 所以在这种情况下,我可以使用$推就好了。 但是我不想重复的名字,$ push在这里失败。 所以我尝试使用$ set,但是$ set不会将具有新名称的对象插入到帐户中。 所以我尝试使用upset:真正的$集,但现在我得到重复的错误。

这里是一个例子,我尝试在帐户中索引名称。 我假设我搞砸了我的查询一些如何。

 var name = "some name"; var fbId = "some fb Id"; var token = "some token"; var username = "some other username"; var password = "some other password"; var query = { fbId: fbId, token: token, "accounts.name":name }; var update = { $set: { accounts: [{ name: name, credentials: { username: username, password: password } }] } }; var options = { upsert: true }; User.update(query, update, options, function (err, numberAffected, rawResponse) { //handle it }); ); 

总结一下我的问题,认为我可以用一个电话来更新这个数字是否合理呢? 或者我应该find对象,replace它的值,然后重新插入到数据库?

您可以使用$ array更新运算符:

 var query = { fbId: fbId, token: token, "accounts.name":name }; var update = { $set: { "accounts.$": [{ //The $ operator goes into the update object name: name, credentials: { username: username, password: password } }] } }; 

根据文件 :

位置$运算符标识数组中的元素以更新,而不显式指定数组中元素的位置。

编辑:

根据这个MongoDB JIRA页面 ,使用$位置运算符的upsert仍然是一个悬而未决的问题。

我search了一下,发现了一个可能的解决scheme,不幸的是,这个解决scheme打败了您一次致电的目标。 它可以在这里find。

总结这个答案,你将不得不首先发送没有upsert标志的更新查询。 然后检查响应以查看文档是否更新,如果不是(这意味着这样的子文档不存在),发送另一个查询与$push操作符插入一个新的子文档在数组中。

如果$push正在为您工作,但是您希望避免向数组添加重复项,请尝试$addToSet 。 它会为数组添加一个值,只要该值不在其中。 查看$ addToSet文档。

更新

从你原来的post:

每次用户添加新帐户时,我都会尝试更新帐户。 所以在这种情况下,我可以使用$推就好了。 但是我不想重复的名字,$ push在这里失败。

 var uniqueAccount = { name:'unique account', credentials: { username:'new username', password:'some secret password' } }; db.accounts.update({fbId: fbId, token: token}, {accounts: {$addToSet: uniqueAccount}});