MongoDB - 涉及列表的upsert

时间:2010-06-28 20:33:42

标签: mongodb nosql

我是MongoDB的新手,想问一下如何写一个涉及upsert和list的更新命令。

基本上我想完成这样的事情:

{"_id" : ObjectId("4c28f62cbf8544c60506f11d"),
"some_other_data":"goes here",
"trips": [
    {"name": "2010-05-10",
     "loc": [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
        {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}]
    },
    {"name": "2010-05-08",
     "loc": [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"},
        {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
        {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}]
    }
]}

请注意:

  • 您提供旅行名称和 当前位置
  • 如果旅程不存在,那就是 需要创建
  • trips.name应该是唯一的 如果它存在,你附加到 位置数组

这是我用$ push组合位置运算符的查询。

    db.mycollection.update({"application_id": "MyTestApp", 
                            "trips.name": "2010-05-10"},
                           {$push: {'trips.$.loc': {"lat":11, "lng":11} }}, 
                           true);

但这会产生如下数据:

> db.mycollection.find({"application_id":"MyTestApp"})          
{ "_id" : ObjectId("4c29044ebf8544c60506f11f"), 
"application_id" : "MyTestApp", 
"trips" : { "$" : { "loc" : [ { "lat" : 11, "lng" : 11 } ] }, 
"name" : "2010-05-10" } 
}

你可以看到

  • “旅行”不是数组
  • 从字面上理解了“$”并创建了一个 关键(doh!)

到目前为止,我对MongoDB非常满意,但是编写复杂的查询肯定会有一个陡峭的学习曲线。

我们将不胜感激。

提前致谢, 艾米

2 个答案:

答案 0 :(得分:4)

你不能混合位置运算符(“$”)和upsert;在插入期间,“$”将被视为字段名称。您不能为新文档执行此操作,只能使用现有文档。

我建议的结构更像这样:

{"_id" : ObjectId("4c28f62cbf8544c60506f11d"),
"some_other_data":"goes here",
"trips": { 
    "2010-05-10":
       [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
        {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}],
    "2010-05-08": 
       [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"},
        {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
        {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}]
    }
}

然后你可以发布这样的更新:

db.mycollection.update({application_id: "MyTestApp", "trips.2010-05-10":{$exists:true}},
                       {$push: {"trips.2010-05-10": {lat:11, lng:11} }}, 
                       true);

导致插入此内容。

> db.mycollection.find()
{ "_id" : ObjectId("4c2931d17b210000000045f0"), 
    "application_id" : "MyTestApp", 
    "trips" : { "2010-05-10" : [ { "lat" : 11, "lng" : 11 } ] } }

再次运行它会给你:

> db.mycollection.find()
{ "_id" : ObjectId("4c2932db7b210000000045f2"), 
    "application_id" : "MyTestApp", 
    "trips" : { "2010-05-10" : 
        [ { "lat" : 11, "lng" : 11 }, 
          { "lat" : 11, "lng" : 11 } ] } }

答案 1 :(得分:1)

已编辑包含正确的解决方案

这正是我学习Mongo的问题 - 您正在寻找与$addToSet命令一起使用的update运算符(see docs here)以及{{1您正在使用的位置运算符。

  

$ addToSet

     

{$ addToSet:{field:value}}

     

仅当数组不在数组中时才向数组添加值。

查询因此变为(db.stack是我用于测试目的的集合),示例运行如下:

$

TEST RUN(带有一些不重要元素空间的缩写):

db.stack.update({ "trips.name":"2010-05-10" }, 
                { $addToSet: { "trips.$.loc":{"lat":11, "lng":12} } }
               );
相关问题