我的MongoDb集合中有一个类似"geo": [39.897867,-121.8909978]
的数组。
我需要做的是交换数组中存在的值。
请帮我解决这个问题。 谢谢......
答案 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上的常见问题解答。
当然最安全的做法就是从客户端使用查找和更新循环,只要该客户端在网络方面尽可能接近数据库服务器,那么它将是大量的线路流量,但它会相当本地化。
在一天结束时,如果最安全的方式不可能(并且可能是由于您的数据库与外部托管服务提供商有关),那么您将无法使用其他更新选项在服务器上,或者只是最终穿过电线流量。
但至少你有一些选择可以考虑。