【问题标题】:mongodb type change to arraymongodb类型更改为数组
【发布时间】:2011-11-16 02:45:17
【问题描述】:

我在 mongodb 中有一个字段,它是一个字符串。 {"field": "some text"},我想将它们全部转换为数组。 {"field": ["some text"]}

我知道我可以遍历所有文档,获取字段,然后更新,但我想知道是否有更简洁的方法。

谢谢。

【问题讨论】:

    标签: javascript mongodb node.js


    【解决方案1】:

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

    更新:另一种选择可能是您为此使用db.evaldb.eval 在服务器上执行,因此更新将在服务器上完成,没有任何流量/延迟。

    我认为唯一的另一个选项是您所描述的 - 通过查询和更新每个选项在客户端上执行此操作。

    【讨论】:

    • 你觉得mongo中的map reduce会更快吗?
    • 这主要取决于您在服务器和客户端之间移动的文档数量和数据量。如果服务器/客户端之间有大量数据移动,那么您希望使用 mapReduce 将处理保留在 MongoDB 内部或尝试 db.eval(正如我刚刚在上面的编辑中添加的那样)。
    • 假设原始发布者已经在 MongoDB shell 中运行,使用db.eval() 的原因是为了原子地执行操作。 By default, db.eval() takes a global write lock while evaluating the JavaScript function。如果代码实际上是在 MongoDB 服务器 JS 线程之外运行(在 Node.js 或 Meteor 应用程序中),那么是的,使用 db.eval() 会减少流量/延迟。
    【解决方案2】:

    但我想知道是否有更清洁的方法..

    简短的回答是否定的。

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

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

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

    【讨论】:

      【解决方案3】:

      试试这个

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

      db.jobs.find( { "jobLocationCity" : { $type : 2 } } ).forEach( function (x) {
          x.jobLocationCity = {"Location":x.jobLocationCity};
          db.jobs.save(x);
      });
      

      查看 $type 的链接 possible values

      【讨论】:

      • 这个答案让我找到了一个我觉得非常简洁的解决方案。我对此处提供的示例所遇到的问题是,由于在 forEach 循环中调用了 save(),因此光标变得混乱,并且该函数会为同一个文档多次调用。解决方法是在foreach之前调用snapshot():db.jobs.find(blah).snapshot().forEach()
      【解决方案4】:

      上面 Nitin Garg 的回答几乎可以工作,除了他的示例从字符串转换为哈希,而不是从字符串转换为数组。

      考虑到 Joel Harris 的 cmets,正确的解决方案如下所示:

      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);
      

      【讨论】:

      • 小修复:x.jobLocationCity = [ x.jobLocationCity ];
      【解决方案5】:

      其实 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);
          }
        }
      )
      

      http://docs.mongodb.org/manual/reference/operators/

      【讨论】:

        【解决方案6】:

        Mongo 4.2开始,db.collection.update()可以接受一个聚合管道,最后允许根据当前值更新一个字段:

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

        • 第二部分[{ $set: { field: { ["$field"] } } }] 是更新聚合管道(注意方括号表示使用聚合管道)。 $set$addFields 的别名)是一个新的聚合运算符,在这种情况下它替换了字段的值(简单地将其包装到一个数组中)。注意field是如何直接根据自己的值($field)修改的。

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

        【讨论】:

          【解决方案7】:

          我认为这是正确的答案:

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

          【讨论】:

          • @XavierGuihot 不一样,检查(字段:)附近的大括号并将其与我的答案进行比较
          【解决方案8】:

          为 MongoDB 4.4 解决。

          db.products.find( { "images" : { $type : 2 } } ).forEach( function (x) { x.images = [ x.images ]; db.products.save(x); });
          

          【讨论】:

            猜你喜欢
            • 2020-11-14
            • 1970-01-01
            • 2017-04-08
            • 2023-01-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-12-12
            • 1970-01-01
            相关资源
            最近更新 更多