javascript - MongoDB 中复杂文档 update() 的解决问题是什么?

标签 javascript mongodb mongoskin mongodb-update

我无法访问我的 MongoDB 集合并更改复杂文档中的值。我尝试了比下面所示的示例更多的变体,各种变体,但它们都失败了。

我想将“air”键的值从“rain”更改为“clear”。在现实生活中,我不会知道键“air”的当前值是“rain”。

请注意,我没有使用 MongoDB _id 对象,并且希望在不使用它的情况下完成此操作。

weatherSys 集合中的 3 个文档:

    {
    "_id" : ObjectId("58a638fb1831c61917f921c5"),
    "SanFrancisco" : [
        { "sky" : "grey" },
        { "air" : "rain" },
        { "ground" : "wet" }
      ]
    }
    {
    "_id" : ObjectId("58a638fb1831c61917f921c6"),
    "LosAngeles" : [
        { "sky" : "grey" },
        { "air" : "rain" },
        { "ground" : "wet" }
      ]
    }
    {
    "_id" : ObjectId("58a638fb1831c61917f921c7"),
    "SanDiego" : [
        { "sky" : "grey" },
        { "air" : "rain" },
        { "ground" : "wet" }
      ]
    }

var docKey   = "LosAngeles";
var subKey   = "air";
var newValue = "clear";

var query       = {};
//var queryKey  = docKey + ".$";  
query[query]    = subKey;                    // query = { }

var set     = {};
var setKey  = docKey + ".0." + subKey;
set[setKey] = newValue;                      // set = { "weather.0.air" : "clear" }

db.collection('weatherSys').update(query, { $set: set }, function(err, result) {
  if (err) throw err;
});

更新1: 好吧,所以我希望我能找到一个比你建议的更简单的布局,但我失败了。我尝试的所有操作都无法在“空中” key 级别进行寻址。因此,我将您的确切 JSON 复制并粘贴到我的集合中并运行它。我正在使用 MongoChef 来操作和测试该集合。

这是我的新布局,通过将 JSON 粘贴 3 次来创建 3 个文档:

enter image description here

当我尝试更新“San Francisco”文档的“air”键时,我得到了意想不到的结果。它没有更新“air”:“dry”,而是在“San Francisco”对象中创建了一个新的“air”键:

enter image description here

所以我想好吧,让我们再次尝试更新,看看会发生什么:

enter image description here

enter image description here

正如您所看到的,它更新了之前创建的“air” key 。我可以解决这个问题并尝试让它以“我的”方式工作,但我只是想让它工作,所以我再次重新配置我的集合布局,沿着什么是“工作”:

enter image description here

并再次运行更新:

enter image description here

然后我通过再次运行更新来验证它:

enter image description here

它有效,我正在多文档环境中正确更新。这是我当前的工作集合布局:

enter image description here

enter image description here

我对此有几个问题-

  1. 我在每个文档中都使用顶级键“天气”。它不会向文档中的信息添加任何内容。是否存在不需要该 Key 及其带来的开销的布局设计更改?

  2. 假设我必须使用“天气”键。它的值是一个数组,但该数组只有一个元素,即包含以下键的对象:城市、天空、空气和地面。寻址是否需要使用只有一个元素的数组?或者我可以摆脱它吗?设计可以不是“weather”:[{}],而是“weather”:{},或者我会再次遇到不可寻址问题吗?

  3. 看来我现在可以 update() 任何键的值:空气、天空和地面,但是 find() 结构是什么来表示在一个中读取键“ground”的值文件的内容?

----> 好的,我想我已经有了这个问题#3- db.weatherSys.find({ "weather.city": "旧金山"}, { "weather.ground": 1 })

  • 在您建议的原始集合布局中,您能否向我解释一下为什么它没有按照您和我的预期进行更新,而是创建了一个新的“城市”对象?
  • 这里有很多。我感谢您坚持下去。

    最佳答案

    您不能使用位置运算符通过键查询数组。

    您可以通过索引访问weather数组,但这意味着您知道数组索引。

    例如,如果您想更新 weather 数组中的 air 元素值。

    db.collection('weatherSys').update( {}, { $set: { "weather.1.air" : "clear"} } );
    

    更新:

    不幸的是,在不知道键的数组索引的情况下,我看不到任何更新值的方法。

    您不需要查询对象,因为您的键是唯一的。

    db.collection('weatherSys').update( {}, { $set: { "SanFrancisco.1.air" : "clear"} } );
    

    如果您想确保 key 存在,则可以使用其他变体。

    db.collection('weatherSys').update( { "SanFrancisco": { $exists: true } }, { $set: { "SanFrancisco.1.air" : "clear"} } );
    

    不确定是否可以,但是否可以将结构更新为以下内容。

    {
        "_id" : ObjectId("58a638fb1831c61917f921c5"),
        "weather" : [
            { 
              "city": "LosAngeles",
              "sky" : "grey" ,
              "air" : "rain" ,
              "ground" : "wet" 
            }
        ]
    }
    

    您现在可以使用 $positional 运算符进行更新。

    db.collection('weatherSys').update( {"weather.city":"LosAngeles"}, { $set: { "weather.$.air" : "clear"} } );
    

    I am using the top level Key "weather" in every document. It adds nothing to the information within the document. Is there a layout design change that would not necessitate that Key and the overhead it brings along?

    我能想到的唯一布局是将所有嵌入属性提升到顶层。抱歉,不知道为什么我第一次没有想到这一点。有时您只需要提出正确的问题即可获得正确的答案。

    {
        "_id" : ObjectId("58a638fb1831c61917f921c5"),
        "city": "LosAngeles",
        "sky" : "grey",
        "air" : "rain",
        "ground" : "wet" 
    }
    

    所有更新都只是顶级更新。

    db.collection('weatherSys').update( {"city":"LosAngeles"}, { $set: { "air" : "clear"} } );
    

    Lets say I have to use the "weather" key. Its value is an array, but that array only has one element, the Object which contains the Keys: city, sky, air, and ground. Does addressing necessitate the use of an array with only one element? Or could I get rid of it. Instead of "weather":[{}] could the design be "weather":{} or would I get into non addressability issues again?

    如果您同意第一个建议,则不适用。

    It appears I can now update() any of the Values for the Keys: air, sky, and ground, but what is the find() structure to say READ the Value of the Key "ground" in one of the documents?

    db.weatherSys.find({ "city": "旧金山"}, { "ground": 1 })

    In the original collection layout that you had suggested, could you explain to me why it did not update as you and I had expected but instead created a new the "city" object?

    这是一个复制粘贴错误。我的意思是建议您现在的工作布局。更新了我之前的布局。

    关于javascript - MongoDB 中复杂文档 update() 的解决问题是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42335266/

    相关文章:

    javascript - 当它位于视口(viewport)中时,将图表饼加载到 div 中

    mongodb - Mongoose 中的自动递增ID

    MongoDB 聚合展开多个数组

    javascript - 将多个对象传递给 Handlebars 模板 - MongoDB、node.js、mongoskin

    javascript - 关于图像大小调整(视口(viewport))的几个问题

    javascript - 如何为多种 Accordion 样式缩短我的 JQuery 脚本?

    mongodb - 使用 mgo.Monotonic 从中学读取

    javascript - 使用 mongoskin 对 mongodb 进行单个查询或多个查询???

    javascript - DOM 子标记名