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

Paw*_*ski 74 mongodb

我有一个文档列表,每个文档都有lat和lon属性(等等).

{ 'lat': 1, 'lon': 2, someotherdata [...] } 
{ 'lat': 4, 'lon': 1, someotherdata [...] }
[...]
Run Code Online (Sandbox Code Playgroud)

我想修改它,使它看起来像这样:

{ 'coords': {'lat': 1, 'lon': 2}, someotherdata [...]} 
{ 'coords': {'lat': 4, 'lon': 1}, someotherdata [...]}
[...]
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有这个:

db.events.update({}, {$set : {'coords': {'lat': db.events.lat, 'lon': db.events.lon}}}, false, true)
Run Code Online (Sandbox Code Playgroud)

但它将db.events.latdb.events.lon视为字符串.如何引用文档的属性?

干杯.

Nie*_*est 205

更新:如果您只需更改文档的结构而不更改值,请参阅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);
  }
)
Run Code Online (Sandbox Code Playgroud)

db.eval()根据您的需要,此类功能还可用于map-reduce作业或服务器端作业.

  • 根据对类似问题的评论,我发现如果没有快照()查找结果,在某些情况下会将光标抛到无限循环中.[更新字段包含其他字段的值](http://stackoverflow.com/questions/2606657/how-can-i-update-field-with-another-fields-value#comment15682010_4260176)尝试`db.events.find() .snapshot().forEach(``//..function goes here``)` (7认同)
  • @AlbertRothman,对于mongo 4.0,使用`.hint({_ id:1})`而不是`.snapshot()`. (2认同)

小智 55

$重命名操作(介绍这个问题被张贴一个月后),使得它很容易做这些事情,你并不需要修改的值.

插入一些测试文档

db.events.insert({ 'lat': 1, 'lon': 2, someotherdata: [] })
db.events.insert({ 'lat': 4, 'lon': 1, someotherdata: [] })
Run Code Online (Sandbox Code Playgroud)

使用$rename运营商

db.events.update({}, {$rename: {'lat': 'coords.lat', 'lon': 'coords.lon'}}, false, true)
Run Code Online (Sandbox Code Playgroud)

结果

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


mjw*_*zor 5

尼尔斯回答。只是为了让人们知道你不能在大型数据库上运行它,如果你可以说它像 Robomongo 这样的远程 shell。您需要通过 ssh 连接到实际服务器的 mongo shell。如果您更愿意进行更新,也可以这样做。

db.Collection.find({***/ possible query /***}).toArray().forEach(
  function(obj){
    obj.item = obj.copiedItem;
    obj.otherItem = obj.copiedItem;
    obj.thirdItem = true;
    obj.fourthItem = "string";
    db.Collection.update({_id: obj._id}, obj);
  }
);
Run Code Online (Sandbox Code Playgroud)