【问题标题】:Saving the result of a MongoDB query保存 MongoDB 查询的结果
【发布时间】:2014-01-13 05:04:35
【问题描述】:

在 mongo shell 中进行研究时,我经常编写相当复杂的查询并希望将结果存储在其他集合中。我知道使用.forEach() 的方法:

db.documents.find(query).forEach(function(d){db.results.insert(d)})

但是每次都写这些东西有点乏味。有没有更清洁的方法?我希望语法类似于db.documents.find(query).dumpTo('collectionName')

【问题讨论】:

    标签: mongodb mongo-shell


    【解决方案1】:

    据我所知,MongoDB 没有内置功能可以做到这一点。

    其他选项是使用mongoexport/mongoimportmongodump/mongorestore 功能。

    在 mongoexport 和 mongodump 中,您可以使用 --query <JSON>-q <JSON> 添加查询选项来过滤结果。

    【讨论】:

      【解决方案2】:

      看起来您正在从 mongo shell 执行查询,它允许您用 javascript 编写代码。您可以将查询结果分配给变量:

      result = db.mycollection.findOne(my_query)
      

      并将结果保存到另一个集合:

      db.result.save(result)
      

      如果要将结果附加到结果集合中,您可能必须删除结果的 _id,以防止重复键错误

      编辑:

      db.mycollection.findOne({'_id':db.mycollection.findOne()['_id']})
      db.foo.save(db.bar.findOne(...))
      

      如果你想保存一个数组,你可以写一个javascript函数。像下面这样的东西应该可以工作(我还没有测试过):

      function save_array(arr) {
          for(var i = 0; i < arr.length; i++) {
              db.result.save(arr[i])
          }
      }
      
      ...
      
      result = db.mycollection.find(...)
      save_array(result)
      

      如果您希望每次启动 mongo shell 时都可以使用该功能,可以将其包含在您的 .mongorc.js 文件中

      【讨论】:

      • 好吧,但我根本不想使用.forEach。如果我可以 db.result.save(db.docs.find(...)) 就好了,但它说“无法保存 DBQuery”
      • 我认为您尝试的操作失败了,因为内部 db.docs.find 查询返回的是数组而不是文档。 Save 可以保存一个文档。查看编辑。
      • 谢谢,我已经发现 DBQuery.toArray() 方法可以满足我的要求。
      • 我的保存数组有问题,我使用了这个方法:´ function save_array(arr) { arr.forEach(element =&gt; db.result.save(element)); };
      【解决方案3】:

      这是我将使用的解决方案:db.results.insert(db.docs.find(...).toArray())

      不过还是有太多的噪音。

      UPD:还有一个选项可以使用聚合管道重写find。然后你可以使用$out operator

      【讨论】:

        【解决方案4】:

        如果您的查询使用聚合运算符,则解决方案与使用 $out 一样。

        我创建了一个名为“tester”的示例集合,其中包含以下记录。

        { "_id" : ObjectId("4fb36bfd3d1c88bfa15103b1"), "name" : "bob", "value" : 5, "state" : "b"}
        
        { "_id" : ObjectId("4fb36c033d1c88bfa15103b2"), "name" : "bob", "value" : 3, "state" : "a"} 
        
        { "_id" : ObjectId("4fb36c063d1c88bfa15103b3"), "name" : "bob", "value" : 7, "state" : "a"}   
        
        { "_id" : ObjectId("4fb36c0c3d1c88bfa1a03b4"), "name" : "john", "value" : 2, "state" : "a"}
        
        { "_id" : ObjectId("4fb36c103d1c88bfa5103b5"), "name" : "john", "value" : 4, "state" : "b"} 
        
        { "_id" : ObjectId("4fb36c143d1c88bfa15103b"), "name" : "john", "value" : 8, "state" : "b"}
        
        { "_id" : ObjectId("4fb36c163d1c88bfa15103a"), "name" : "john", "value" : 6, "state" : "a"}
        

        现在我使用聚合运算符执行分组,然后使用这个神奇的运算符“$out”将结果保存到新集合中。

        db.tester.aggregate([{$group:{
                                        _id:{name:"$name",state:"$state"},
                                        min:{$min:"$value"},
                                        max:{$max:"$value"},
                                       } },
                               {$out:"tester_max_min"}
                             ])
        

        查询的主要目的是按名称和状态进行分组,并找到每个单独组的最小值和最大值,然后将结果保存到名为“tester_max_min”的新集合中

        db.tester_max_min.find();
        

        形成的新集合将包含以下文档:

        { "_id" : { "name" : "john", "state" : "b" }, "min" : 4, "max" : 8 }
        
        { "_id" : { "name" : "john", "state" : "a" }, "min" : 2, "max" : 6 }
        
        { "_id" : { "name" : "bob", "state" : "a" }, "min" : 3, "max" : 7 }
        
        { "_id" : { "name" : "bob", "state" : "b" }, "min" : 5, "max" : 5 }
        

        我仍然需要探索 $out 有多大帮助,但它对任何聚合器运营商来说都是一种魅力。

        【讨论】:

        • $out 将完全替换原始集合,如果它指向与聚合相同的集合,因此如果有 $match 过滤器,所有不匹配的都将被删除。
        猜你喜欢
        • 2021-04-19
        • 1970-01-01
        • 2017-08-11
        • 2015-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-03
        相关资源
        最近更新 更多