MongoDB中复杂文档update()的寻址问题是什么?

时间:2017-02-20 01:52:14

标签: javascript mongodb mongoskin mongodb-update

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

我想将钥匙“空气”的价值从“雨”改为“清除”。在现实生活中,我不会知道关键“空气”的当前价值是“下雨”。

注意,我没有使用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;
});

UPDATE-1: 好的,所以我希望我能找到比你建议的更简单的布局,但我失败了。我试过的所有东西都无法在“空中”钥匙层找到。因此,我将您的确切JSON复制并粘贴到我的收藏中并运行它。我正在使用MongoChef来操作和测试集合。

这是我在3次粘贴JSON以创建3个文档时的新布局:

enter image description here

当我尝试更新“旧金山”文档的“空中”键时,我得到了意想不到的结果。而不是更新“空气”:“干”,它在“旧金山”对象中创建了一个新的“空气”键:

enter image description here

所以我想好了,让我们再试一次,看看会发生什么:

enter image description here

enter image description here

正如您所看到的,它更新了之前创建的“air”键。我可以解决这个问题并尝试让它以“我的”方式工作,但我只是希望它能够工作,所以我再次重新配置我的集合布局,按照“工作”的方式:

enter image description here

再次运行更新:

enter image description here

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

enter image description here

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

enter image description here

enter image description here

我对此有几个问题 -

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

  2. 让我说我必须使用“天气”键。它的值是一个数组,但该数组只有一个元素,Object包含Keys:city,sky,air和ground。寻址是否需要使用只有一个元素的数组?或者我可以摆脱它。而不是“天气”:[{}]设计可能是“天气”:{}还是我会再次陷入非寻址问题?

  3. 看来我现在可以更新()键的任何值:空中,天空和地面,但是什么是find()结构来说明将键“地面”的值读入一个文件?

  4. ---->好的,我想我有这个问题#3- db.weatherSys.find({“weather.city”:“San Francisco”},{“weather.ground”:1})

    1. 在您建议的原始收藏布局中,您能否向我解释为什么它没有按照您的预期更新,而是创建了一个新的“城市”对象?
    2. 这里有很多。我很感激你坚持下去。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

更新

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

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

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

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

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

我在每个文档中使用顶级键“天气”。它补充道   对文档中的信息没有任何意义。有布局吗?   设计变更,不需要钥匙和开销   带来了吗?

我能想到的唯一布局是将所有嵌入属性提升到顶层。对不起,不知道为什么我第一次没想到这个。有时你只需要一个正确的问题来得到正确的答案。

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

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

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

假设我必须使用“天气”键。它的值是一个数组,但是   该数组只有一个元素,包含Keys的Object:   城市,天空,空气和地面。解决是否需要使用   只有一个元素的数组?或者我可以摆脱它。代替   “天气”:[{}]设计可能是“天气”:{}或者我会进入   再次出现非可解决性问题?

如果您对第一个建议没问题,则不适用。

  

看来我现在可以更新()键的任何值:air,   天空和地面,但什么是find()结构说READ   其中一个文件中关键“基础”的价值?

db.weatherSys.find({“city”:“San Francisco”},{“ground”:1})

  

在您建议的原始收藏布局中,您能吗?   向我解释为什么它没有像你和我预期的那样更新   而是创建了一个新的“城市”对象?

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