MongoDB: 使用同一文档中的数据更新文档

我有一个文档列表,每个文档都具有 lat 和 lon 属性(以及其他属性)。

{ 'lat': 1, 'lon': 2, someotherdata [...] }
{ 'lat': 4, 'lon': 1, someotherdata [...] }
[...]

I want to modify it so that it looks like this:

{ 'coords': {'lat': 1, 'lon': 2}, someotherdata [...]}
{ 'coords': {'lat': 4, 'lon': 1}, someotherdata [...]}
[...]

到目前为止,我得到了这个:

db.events.update({}, {$set : {'coords': {'lat': db.events.lat, 'lon': db.events.lon}}}, false, true)

但是它将 Db.events. latDB.Events Lon视为字符串。如何引用文档的属性?

干杯。

69402 次浏览

CLI 的?我认为你必须首先取出这些值,然后把它们赋给一个变量。然后运行更新命令。

Or (I haven't tried) remove 'db' from the string. events.lat and events.lon If it works, you will still have multiple values, the old values for "lat" and "lon" and the new array you created.

更新: 如果您只需要更改文档的结构而不需要更改值,请参阅 Gipset 的回答以获得更好的解决方案。


根据对 更新文档页面的注释(现在不可用) ,您不能从 update()中引用当前文档的属性。

您必须遍历所有文档,并像下面这样更新它们:

db.events.find().snapshot().forEach(
function (e) {
// update document, using its own properties
e.coords = { lat: e.lat, lon: e.lon };


// remove old properties
delete e.lat;
delete e.lon;


// save the updated document
db.events.save(e);
}
)

根据您的需要,这样的函数也可以用于 map-reduce 作业或服务器端 db.eval()作业。

$重命名操作符(在这个问题发布一个月后引入)使得在不需要修改值的情况下做这些事情变得非常容易。

Insert some test documents

db.events.insert({ 'lat': 1, 'lon': 2, someotherdata: [] })
db.events.insert({ 'lat': 4, 'lon': 1, someotherdata: [] })

使用 $rename操作符

db.events.update({}, {$rename: {'lat': 'coords.lat', 'lon': 'coords.lon'}}, false, true)

结果

db.events.find()
{
"_id" : ObjectId("5113c82dd28c4e8b79971add"),
"coords" : {
"lat" : 1,
"lon" : 2
},
"someotherdata" : [ ]
}
{
"_id" : ObjectId("5113c82ed28c4e8b79971ade"),
"coords" : {
"lat" : 4,
"lon" : 1
},
"someotherdata" : [ ]
}

只要您同意创建数据的副本,聚合框架就可以在这里作为替代方案使用。如果您希望使用其他操作符,也可以选择对数据进行更多操作,但是您只需要 $project操作符。它在空间上有些浪费,但是在某些用途上可能更快、更合适。为了说明这一点,我首先将一些示例数据插入到 foo集合中:

db.foo.insert({ 'lat': 1, 'lon': 2, someotherdata : [1, 2, 3] })
db.foo.insert({ 'lat': 4, 'lon': 1, someotherdata : [4, 5, 6] })

Now, we just use $project to rework the lat and lon fields, then send them to the newfoo collection:

db.foo.aggregate([
{$project : {_id : "$_id", "coords.lat" : "$lat", "coords.lon" : "$lon", "someotherdata" : "$someotherdata" }},
{ $out : "newfoo" }
])

然后检查 newfoo,看看我们修改过的数据:

db.newfoo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }

Once you are happy with the new data, you can then use the renameCollection() command to drop the old data and use the new data under the old name:

> db.newfoo.renameCollection("foo", true)
{ "ok" : 1 }
> db.foo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }

最后一个注意事项——在 服务器编号7944完成之前,你不能像 这个答案中建议的那样通过提示 _id索引来完成快照操作,因此如果其他地方的活动导致文档移动,那么你最终可能不止一次地点击一个文档。因为在这个示例中插入了 _id字段,所以任何这样的情况都会导致一个惟一的键冲突,所以最终不会出现 Dupes,但是您可能拥有一个“旧”版本的文档。像往常一样,在删除数据之前彻底检查数据,最好是备份数据。

我们可以使用 Mongo 脚本在运行中操作数据。它对我很有用!

我使用这个脚本来更正我的地址数据。

当前地址示例: “ No. 12,FIFTH AVENUE,”。

我想删除最后一个冗余逗号,预期的新地址“第五大道12号”。

var cursor = db.myCollection.find().limit(100);


while (cursor.hasNext()) {
var currentDocument = cursor.next();


var address = currentDocument['address'];
var lastPosition = address.length - 1;


var lastChar = address.charAt(lastPosition);


if (lastChar == ",") {


var newAddress = address.slice(0, lastPosition);




currentDocument['address'] = newAddress;


db.localbizs.update({_id: currentDocument._id}, currentDocument);


}
}

希望这个能帮上忙!