{
x: 120,
y: 30
}
//转化成
{
position: {
type: 'Point',
coordinates: [120, 30]
}
}
你需要的是一个脚本,将数据库中的doc转化成你需要的格式。鉴于update的空间消耗,建议存在其他的collection中。
@haozxuan 谢谢
我目前用 nodejs 解决了,效率不高
collection.find({}).each(function (err, item) {
if(item === null) {
logger.trace('end');
}
collection.update({id: item._id}, {
$set: {
position: {
type: 'Point',
coordinate: [item.x, item.y]
}
}
}, function (err, data) {
logger.trace('......');
})
});
@fiftyk 允许x.y字段的重复吗?还有你find({})这样做的话,数据量打的时候有些不妥。而且上面提到的update空间消耗问题,由于之前insert时候只有xy字段所以预分配空间会比较小,加入新的结构后会因为空间不够另外开辟空间,换句话说会造成磁盘碎片,而且约到后期update会越慢。当然这些都是量大的时候,如果仅仅是开发阶段你的方案还是不错的。
@haozxuan 自己机器上做测试的, 30W+条记录,
> db.collection.dataSize()
return:
5921135744
像你说的 update 越来越慢
另外我不用 find({}).each
用什么查询所有数据并更新呢,有什么迭代器吗?
小改动 update 时的查询参数由 {id: : item._id}
改为 {_id: : item._id}
, 速度暴增! _id
有索引,唉
@fiftyk find({})没有limit,将30W数据全部读取到内存中欠妥哟
@haozxuan
非常不妥,除了 x
和 y
这两个字段,还有其他很多字段,非常不妥,还在想办法。
db.collection.find({}).skip(0).limit(1000).toArray(function (err, items) {
//...
db.collection.find({}).skip(1000).limit(1000).toArray(function (err, items) {
//...
db.collection.find({}).skip(2000).limit(1000).toArray(function (err, items) {
//...
}
}
});
这样如何?
skip 的这些步骤可以打到for loop里,减少重复代码
@fiftyk 建议看下mongodb权威指南,第二版。 上述方案中有两个比较大的问题: 1、重新开一个collection,把新规则的数据放在另外的表中(姑且这么叫吧)。好处:不会由于update导致磁盘碎片或者update后期越来越慢 2、尽量不要使用skip,这个操作符的工作原理是首先查询到所有符合要求的集合,然后舍弃前n页,这样在数据量大的时候会很慢,具体分页方案网上有很多可以借鉴下。
另外如果性质是数据迁移的话,建议写一个nodejs程序让他跑完所有数据。当然,如果是暂存的一个数据状态的话,也可以起一个nodejs 转数据服务让他跑。