交换MongoDB数组中的值

时间:2014-03-11 13:25:25

标签: mongodb mongodb-query

我的MongoDb集合中有一个类似"geo": [39.897867,-121.8909978]的数组。

我需要做的是交换数组中存在的值。

请帮我解决这个问题。 谢谢......

2 个答案:

答案 0 :(得分:8)

您可以使用数组索引进行交换。首先找到并交换它。

db.myCollection.find().forEach(function(doc){
        db.myCollection.update({_id: doc._id},
          {$set: {"geo.0": doc.geo[1], "geo.1": doc.geo[0]}})
    })

答案 1 :(得分:0)

好的,既然你似乎没有在明显的迭代循环中挣扎,而你担心项目的数量,那么让我们来看看你的选择:

mapReduce可以和选项一起执行此操作。但请注意,您的文档格式不一样。因此,如果您可以在应用程序中重命名已使用的集合,那么这将是一种安全复制集合的方法。但如果您的收藏品定期更新,这将不是一个选择。

db.collection.mapReduce(
    function() {

        var t = this.geo[0];
        this.geo[0] = this.geo[1];        
        this.geo[1] = t;

        emit( this._id, this );
    },
    function(){},
    {
        "out" : { "replace": "newcollection" }
    }
)  

然后你可以安全地使用db.eval()和#34;" remodel"回到原来的形式:

db.eval(function(){
    db.newcollection.find().forEach(function(doc) {
        var newDoc = {};

        Object.keys(doc.value).forEach(function(key) {
            newDoc["key"] = doc.value["key"];
        });
        db.newcollection.update(doc._id,newDoc); 
    });
})

这会给你一个"固定"用另一个名字收集。您可以将应用程序指向该应用程序,但如果不能,则可以使用renameCollection来完成工作:

db.collection.drop();
db.newcollection.rename("collection");

但是整个过程中会有很多磁盘颠簸,当然,无论如何你都需要为集合重新创建任何索引。

此外,您可以直接前往现有收藏集的db.eval()

db.eval(function(){
    db.collection.find().forEach(function(doc){
        db.collection.update(
          {_id: doc._id},
          {"$set": {"geo.0": doc.geo[1], "geo.1": doc.geo[0]}}
        );
    });
})

但请阅读有关此文档的文档。在执行此操作时,您将以任何速率锁定数据库。另请参阅concurrency上的常见问题解答。

当然最安全的做法就是从客户端使用查找和更新循环,只要该客户端在网络方面尽可能接近数据库服务器,那么它将是大量的线路流量,但它会相当本地化。

在一天结束时,如果最安全的方式不可能(并且可能是由于您的数据库与外部托管服务提供商有关),那么您将无法使用其他更新选项在服务器上,或者只是最终穿过电线流量。

但至少你有一些选择可以考虑。