Question

When doing a research in mongo shell I often write quite complex queries and want the result to be stored in other collection. I know the way to do it with .forEach():

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

But it's kind of tedious to write that stuff each time. Is there a cleaner way? I'd like the syntax to be something like db.documents.find(query).dumpTo('collectionName').

Was it helpful?

Solution

Here's a solution I'll use: db.results.insert(db.docs.find(...).toArray())

There is still too much noise, though.

UPD: There is also an option to rewrite find using aggregation pipeline. Then you can use $out operator.

OTHER TIPS

It looks like you are doing your queries from the mongo shell, which allows you to write code in javascript. You can assign the result of queries to a variable:

result = db.mycollection.findOne(my_query)

And save the result to another collection:

db.result.save(result)

You might have to remove the _id of the result if you want to append it to the result collection, to prevent a duplicate key error

Edit:

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

If you want to save an array, you can write a javascript function. Something like the following should work (I haven't tested it):

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

...

result = db.mycollection.find(...)
save_array(result)

If you want the function to be available every time you start mongo shell, you can include it in your .mongorc.js file

As far as I know, there isn't built-in functionality to do this in MongoDB.

Other options would be to use mongoexport/mongoimport or mongodump/mongorestore functionalities.

In both mongoexport and mongodump you can filter the results by adding query options using --query <JSON> or -q <JSON>.

If your query is using an aggregation operator then the solution is as sample as using the $out.

I created a sample Collection with the name "tester" which contain the following records.

{ "_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"}

Now using the aggregate operator I perform a group by and then save the result into a new collection using this magical operator "$out".

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

What basically the query is trying to do is, group by name & state and find the min and max values for each individual group, and then save the result into a new collection named "tester_max_min"

db.tester_max_min.find();

The new collection formed will have the following documents in it :

{ "_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 }

I still need to explore how helpful can $out is but it works like a charm for any aggregator operator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top