MongoDB-upsert包含列表
我是一个MongoDB新手,想问一下如何编写涉及upsert和list的更新命令 基本上,我想完成以下任务:MongoDB-upsert包含列表,mongodb,nosql,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 201
{"_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"}]
}
]}
> db.mycollection.find({"application_id":"MyTestApp"})
{ "_id" : ObjectId("4c29044ebf8544c60506f11f"),
"application_id" : "MyTestApp",
"trips" : { "$" : { "loc" : [ { "lat" : 11, "lng" : 11 } ] },
"name" : "2010-05-10" }
}
请注意:
- 您提供旅行名称和 当前位置
- 如果行程不存在,则它将 需要创建
- trips.name应该是唯一的,以便 如果存在,则将其附加到 位置阵列
db.mycollection.update({"application_id": "MyTestApp",
"trips.name": "2010-05-10"},
{$push: {'trips.$.loc': {"lat":11, "lng":11} }},
true);
但这会产生如下数据:
{"_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"}]
}
]}
> db.mycollection.find({"application_id":"MyTestApp"})
{ "_id" : ObjectId("4c29044ebf8544c60506f11f"),
"application_id" : "MyTestApp",
"trips" : { "$" : { "loc" : [ { "lat" : 11, "lng" : 11 } ] },
"name" : "2010-05-10" }
}
你可以看到
- “trips”不是数组
- 它从字面上取了“$”并创建了一个 用那个键(doh!)
Amie编辑以包含正确的解决方案 这正是我在learning Mongo中遇到的问题-您正在查找与
update
命令一起使用的$addToSet
操作符(),该操作符与您使用的$
位置操作符一起使用
$addToSet
{$addToSet:{field:value}
仅当其不在数组中时才向数组添加值
因此,查询变成(db.stack是我用于测试目的的集合),下面是运行示例:
db.stack.update({ "trips.name":"2010-05-10" },
{ $addToSet: { "trips.$.loc":{"lat":11, "lng":12} } }
);
测试运行(使用一些不重要的元素空间缩写):
不能混合使用位置运算符($)和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);
然后您可以发布如下更新:
{"_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 } ] } }
感谢您的回复@Anthony Morelli。我尝试了$addToSet,并且必须传入upsert=true才能第一次插入trip。当我将行程名称更改为其他名称时,实际上会创建一个新文档,而不是使用当前文档。我们如何指定“trips”是一个数组?您具体运行了什么查询$addToSet仅适用于数组,因此我认为规范不是问题所在。我准确地运行了您的查询,但它没有创建文档,因此我传入了upsert=true。在创建第一个文档之后,当它第二次运行时,它创建了第二个文档,而不是将其附加到前一个文档中..我相信我已经修复了它-请参阅编辑。基本上,我忘记了位置操作符,它是指定trips数组中应该更新的项所必需的。新的查询是
db.stack.update({“trips.name”:“2010-05-10”},{$addToSet:{“trips.$.loc”:{“lat”:11,“lng”:12}}})代码>-我用您现有的模式对其进行了测试,效果很好。如果说只有在文档已经存在的情况下才有效,是否正确?(正如Scott指出的,我们不能同时使用“$”和upsert),但我可以看出这在某些情况下是有用的。感谢全面的更新!这与我试图实现的目标非常接近。谢谢@Scott Hernandez。使用此模式,是否可以检索“trips”中的键列表?(“2010-050-10”,等等)db.mycollection.find({“application_id”:“MytestApp”},{“trips”:true})返回整个“trips”散列。我最终使用了这个方法。谢谢你的解决方案,斯科特!这里的问题是,您无法在行程中查询某些内容,例如查找行程为lat 21.321231的文档(因为mongo(今天)无法找到字段路径的“通配符”部分)。再次检查我下面的答案-我对其进行了编辑,以包括我认为是解决方案的内容(或者至少是应该让您非常接近的内容)看这个。类似的东西。