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

Posted

技术标签:

【中文标题】MongoDB。如何更新数组内的json属性【英文标题】:MongoDB. How to update json property inside an array 【发布时间】:2015-07-30 17:21:25 【问题描述】:

我正在使用平均堆栈。我对此感到不舒服,并且让自己陷入困境。我已经看到使用 set 或 push 更新记录的示例,但是因为我试图更新 json 对象数组中的 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 就好了。但我不想要重复的名称,并且 $push 在这里失败。所以我尝试使用 $set,但 $set 没有将具有新名称的对象插入到帐户中。所以我尝试使用 upsert:true 和 $set,但现在我得到了重复的错误。

这是我尝试在帐户中索引名称的示例。我假设我搞砸了我的查询。

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
    );
);

总结一下我的问题,认为我可以通过一个电话更新它是否合理,如果可以,如何更新?还是我应该找到对象,替换它的值,然后将其重新插入数据库?

【问题讨论】:

【参考方案1】:

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

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
            
        ]
    
;

根据documentation:

位置 $ 运算符标识要更新的数组中的元素 没有明确指定元素在 数组。

编辑:

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

我四处搜索并找到了一个可能的解决方案,不幸的是,这破坏了您通过一个电话实现这一目标的目标。可以找到here。

总结这个答案,您必须首先发送不带upsert 标志的更新查询。然后检查响应以查看文档是否已更新,如果没有(这意味着这样的子文档不存在),则发送另一个带有 $push 运算符的查询以在数组中插入新的子文档。

【讨论】:

得到以下错误响应。位置运算符未从查询中找到所需的匹配项。未扩展更新:accounts.$ 哦,您还需要将 upsert 标志设置为 true。 是的。当我注释掉 upsert 标志时,我没有收到任何错误,但它也没有更新任何内容。 您在编辑中提供的链接有一个有效的答案。谢谢。【参考方案2】:

如果$push 适合您,但您想避免向数组添加重复项,请尝试$addToSet。它将向数组添加一个值,只要该值不在其中。查看$addToSet 文档。

更新

来自您的原始帖子:

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

var uniqueAccount = 
  name:'unique account',
  credentials: 
    username:'new username',
    password:'some secret password'
  
;

db.accounts.update(fbId: fbId, token: token,
  accounts: $addToSet: uniqueAccount);

【讨论】:

以上是关于MongoDB。如何更新数组内的json属性的主要内容,如果未能解决你的问题,请参考以下文章

更新数组mongodb内的嵌套数组[重复]

使用 mongoose 在 mongoDb 中更新数组内的对象 [重复]

如何在 MySQL 中的 JSON 数组内的元素中提取特定属性的所有值?

mongodb `$lookup` 或 `join` 与对象数组内的属性

如何更新firestore中数组内的对象? [复制]

如何在 Eloquent 中查询 JSON 列内的数组