我在mongodb中有一个字符串字段。{"field": "some text"},我想把它们都转换成数组。{"field": ["some text"]}我知道我可以循环遍历所有文档,得到字段,然后更新,但我想知道是否有一个更干净的方法。
{"field": "some text"}
{"field": ["some text"]}
9avjhtql1#
从Mongo 4.2开始,db.collection.update()可以接受聚合管道,最后允许基于字段的当前值对其进行更新:
Mongo 4.2
db.collection.update()
// { field: "some text" } db.collection.updateMany( {}, [{ $set: { field: ["$field"] } }] ) // { field: [ "some text" ] }
{}
[{ $set: { field: { ["$field"] } } }]
$set
$addFields
field
$field
jdgnovmf2#
上面Nitin Garg的答案几乎是有效的,除了他的例子从字符串转换为哈希,而不是从字符串转换为数组。考虑到Joel Harris的评论,正确的解决方案应该是:
db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach( function (x) { x.jobLocationCity = [ jobLocationCity ]; db.jobs.save(x); });
或者,如果使用db.eval:
function f() { db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach( function (x) { x.jobLocationCity = [ jobLocationCity ]; db.jobs.save(x); }); } db.eval(f);
j13ufse23#
实际上,查找({“jobLocationCity”:{ $type:2 } })将无法正常工作,因为如果您下次运行更新脚本,它将再次将['mystring']元素视为字符串类型。您应该使用类似以下的方法来防止它:
db.message_info.find( { "jobLocationCity" : { $type : 2 } } ).snapshot().forEach( function (x) { if (!Array.isArray(x.jobLocationCity)){ x.jobLocationCity = [ x.jobLocationCity ]; db.jobs.save(x); } } )
请参阅http://docs.mongodb.org/manual/reference/operators/
brvekthn4#
你可以在map/reduce的Reduce函数中完成,把所有的处理都保存在mongodb中,本质上你可以使用map/reduce把结果放到一个新的集合中,然后你可以把它们复制回旧的集合(或者删除旧的集合并重命名新的集合),这样做的好处是把所有的东西都保存在mongo中。
Update:另一个选择是使用db.eval。db.eval在服务器上执行,因此更新将在服务器上完成,没有任何流量/延迟。
db.eval
我认为唯一的另一个选择是如你所描述的-在客户端上通过查询和更新每个文件来完成。
falq053o5#
试试这个这是为了在mongoDB中将字段的类型从字符串更改为数组
db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).forEach( function (x) { x.jobLocationCity = {"Location":x.jobLocationCity}; db.jobs.save(x); });
有关$type的可能值,请参阅链接
0ejtzxu16#
但我想知道有没有更干净的方法。简短的回答是否定的。MongoDB没有任何单个操作或命令来执行“更改类型”。最快的方法可能是使用其中一个驱动程序并进行更改。您可以使用shell并编写一个for循环,但就原始速度而言,其他驱动程序可能更快。也就是说,这个过程中最慢的部分是将所有数据从磁盘加载到内存中进行更改,然后将这些数据刷新回磁盘,即使使用一个神奇的“change type”命令也是如此。
mklgxw1f7#
我想这才是正确答案:
db.collection.update({},[{$set:{field:["$field"]}}],{ multi: true })
iibxawm48#
为MongoDB 4.4解决。
db.products.find( { "images" : { $type : 2 } } ).forEach( function (x) { x.images = [ x.images ]; db.products.save(x); });
8条答案
按热度按时间9avjhtql1#
从
Mongo 4.2
开始,db.collection.update()
可以接受聚合管道,最后允许基于字段的当前值对其进行更新:{}
是匹配查询,过滤要更新的文档(在本例中是所有文档)。[{ $set: { field: { ["$field"] } } }]
是更新聚合管道(请注意方括号表示使用聚合管道)。$set
($addFields
的别名)是一个新的聚合运算符,在本例中,它替换字段的值(只是将其 Package 到数组中)。请注意field
是如何直接根据其自身的值($field
)修改的。jdgnovmf2#
上面Nitin Garg的答案几乎是有效的,除了他的例子从字符串转换为哈希,而不是从字符串转换为数组。
考虑到Joel Harris的评论,正确的解决方案应该是:
或者,如果使用db.eval:
j13ufse23#
实际上,查找({“jobLocationCity”:{ $type:2 } })将无法正常工作,因为如果您下次运行更新脚本,它将再次将['mystring']元素视为字符串类型。
您应该使用类似以下的方法来防止它:
请参阅http://docs.mongodb.org/manual/reference/operators/
brvekthn4#
你可以在map/reduce的Reduce函数中完成,把所有的处理都保存在mongodb中,本质上你可以使用map/reduce把结果放到一个新的集合中,然后你可以把它们复制回旧的集合(或者删除旧的集合并重命名新的集合),这样做的好处是把所有的东西都保存在mongo中。
Update:另一个选择是使用db.eval。
db.eval
在服务器上执行,因此更新将在服务器上完成,没有任何流量/延迟。我认为唯一的另一个选择是如你所描述的-在客户端上通过查询和更新每个文件来完成。
falq053o5#
试试这个
这是为了在mongoDB中将字段的类型从字符串更改为数组
有关$type的可能值,请参阅链接
0ejtzxu16#
但我想知道有没有更干净的方法。
简短的回答是否定的。
MongoDB没有任何单个操作或命令来执行“更改类型”。
最快的方法可能是使用其中一个驱动程序并进行更改。您可以使用shell并编写一个for循环,但就原始速度而言,其他驱动程序可能更快。
也就是说,这个过程中最慢的部分是将所有数据从磁盘加载到内存中进行更改,然后将这些数据刷新回磁盘,即使使用一个神奇的“change type”命令也是如此。
mklgxw1f7#
我想这才是正确答案:
iibxawm48#
为MongoDB 4.4解决。