Save Subset of MongoDB Collection to Another Collection

I have a set like so

{date: 20120101}
{date: 20120103}
{date: 20120104}
{date: 20120005}
{date: 20120105}

How do I save a subset of those documents with the date '20120105' to another collection?

i.e db.subset.save(db.full_set.find({date: "20120105"}));


Solution 1:

I would advise using the aggregation framework:

db.full_set.aggregate([ { $match: { date: "20120105" } }, { $out: "subset" } ])

It works about 100 times faster than forEach at least in my case. This is because the entire aggregation pipeline runs in the mongod process, whereas a solution based on find() and insert() has to send all of the documents from the server to the client and then back. This has a performance penalty, even if the server and client are on the same machine.

Solution 2:

Here's the shell version:

db.full_set.find({date:"20120105"}).forEach(function(doc){
   db.subset.insert(doc);
});

Note: As of MongoDB 2.6, the aggregation framework makes it possible to do this faster; see melan's answer for details.

Solution 3:

Actually, there is an equivalent of SQL's insert into ... select from in MongoDB. First, you convert multiple documents into an array of documents; then you insert the array into the target collection

db.subset.insert(db.full_set.find({date:"20120105"}).toArray())

Solution 4:

The most general solution is this:

Make use of the aggregation (answer given by @melan):

db.full_set.aggregate({$match:{your query here...}},{$out:"sample"})
db.sample.copyTo("subset")

This works even when there are documents in "subset" before the operation and you want to preserve those "old" documents and just insert a new subset into it.

Care must be taken, because the copyTo() command replaces the documents with the same _id.

Solution 5:

There's no direct equivalent of SQL's insert into ... select from ....

You have to take care of it yourself. Fetch documents of interest and save them to another collection.

You can do it in the shell, but I'd use a small external script in Ruby. Something like this:

require 'mongo'

db = Mongo::Connection.new.db('mydb')

source = db.collection('source_collection')
target = db.collection('target_collection')

source.find(date: "20120105").each do |doc|
  target.insert doc
end