Javascript mongodb类型更改为数组

Javascript mongodb类型更改为数组,javascript,mongodb,node.js,Javascript,Mongodb,Node.js,我在mongodb中有一个字段是字符串{“字段”:“一些文本”},我想将它们全部转换为数组{“字段”:[“某些文本”]} 我知道我可以循环浏览所有文档,获取字段,然后更新,但我想知道是否有更干净的方法 谢谢。您可以在map/Reduce的Reduce功能中执行此操作,以将所有处理保留在mongodb中。基本上,您可以使用map/reduce将结果放入新集合,然后将它们复制回旧集合(或者删除旧集合并重命名新集合)。这样做的好处是将所有内容都保存在mongo中 更新:另一个选项可能供您使用db.ev

我在mongodb中有一个字段是字符串<代码>{“字段”:“一些文本”},我想将它们全部转换为数组<代码>{“字段”:[“某些文本”]}

我知道我可以循环浏览所有文档,获取字段,然后更新,但我想知道是否有更干净的方法


谢谢。

您可以在map/Reduce的Reduce功能中执行此操作,以将所有处理保留在mongodb中。基本上,您可以使用map/reduce将结果放入新集合,然后将它们复制回旧集合(或者删除旧集合并重命名新集合)。这样做的好处是将所有内容都保存在mongo中

更新:另一个选项可能供您使用
db.eval
在服务器上执行,因此更新将在服务器上完成,而不会产生任何流量/延迟

我认为唯一的另一个选择是如您所描述的,通过查询和更新每个选项在客户机上执行

但是我想知道是否有更干净的方法

简而言之,答案是否定的

MongoDB没有执行“更改类型”的任何单个操作或命令

最快的方法是使用其中一个驱动程序并进行更改。您可以使用shell并编写for循环,但就原始速度而言,其他驱动程序可能更快

也就是说,这个过程中最慢的部分是将所有数据从磁盘加载到要更改的内存中,然后将这些数据刷新回磁盘。即使使用神奇的“更改类型”命令,这也是正确的。

试试这个

这是为了在mongoDB中将字段的类型从字符串更改为数组

db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).forEach( function (x) {
    x.jobLocationCity = {"Location":x.jobLocationCity};
    db.jobs.save(x);
});
有关$type的详细信息,请参见链接
尼廷·加格(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);
实际上,find({“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);
    }
  }
)

请参见从
Mongo 4.2开始,可以接受聚合管道,最后允许根据字段的当前值更新字段:

// { field: "some text" }
db.collection.update(
  {},
  [{ $set: { field: ["$field"] } }],
  { multi: true }
)
// { field: [ "some text" ] }
  • 第一部分是匹配查询,过滤要更新的文档(在本例中为所有文档)

  • 第二部分是更新聚合管道(注意方括号表示使用聚合管道)。(别名
    $addFields
    )是一个新的聚合运算符,在本例中,它将替换字段的值(只需将其包装到数组中)。请注意,
    字段
    是如何根据其自身的值(
    $field
    )直接修改的

  • 不要忘记
    {multi:true}
    (或者使用
    updateMany
    ),否则只会更新第一个匹配的文档


    • 我认为这是正确的答案:

      db.collection.update({},[{$set:{field:["$field"]}}],{ multi: true })
      

      您认为mongo中的map reduce会更快吗?主要取决于您在服务器和客户端之间移动了多少文档和多少数据。如果有大量数据在服务器/客户机之间移动,那么您希望使用mapReduce在MongoDB内部进行处理,或者尝试使用db.eval(正如我刚才在上面的编辑中添加的那样)。假设原始海报已经在MongoDB shell中工作,那么使用
      db.eval()
      的原因是,该操作是以原子方式执行的。如果代码实际上是在MongoDB server JS线程之外运行的(在Node.JS或Meteor应用程序中),那么是的,使用
      db.eval()
      可以减少流量/延迟。这个答案让我找到了一个我觉得非常简洁的解决方案。我在这里提供的示例中遇到的问题是,因为在forEach循环中调用了save(),所以游标被弄乱了,同一个文档的函数会被多次调用。解决方案是在foreach之前调用snapshot():db.jobs.find(blah).snapshot().foreach()小补丁:x.jobLocationCity=[x.jobLocationCity]@XavierGuihot不,不一样,检查(字段:)附近的花括号,并将其与我的答案进行比较