Ответ 1
Вот версия оболочки:
db.full_set.find({date:"20120105"}).forEach(function(doc){
db.subset.insert(doc);
});
Примечание: Начиная с MongoDB 2.6, структура агрегации позволяет делать это быстрее; см. мелан ответ для деталей.
У меня есть такой набор
{date: 20120101}
{date: 20120103}
{date: 20120104}
{date: 20120005}
{date: 20120105}
Как сохранить подмножество этих документов с датой '20120105' в другую коллекцию?
i.e db.subset.save(db.full_set.find({date: "20120105"}));
Вот версия оболочки:
db.full_set.find({date:"20120105"}).forEach(function(doc){
db.subset.insert(doc);
});
Примечание: Начиная с MongoDB 2.6, структура агрегации позволяет делать это быстрее; см. мелан ответ для деталей.
В качестве более нового решения я бы посоветовал использовать структуру Aggregation для проблемы:
db.full_set.aggregate([ { $match: { date: "20120105" } }, { $out: "subset" } ]);
Он работает примерно в 100 раз быстрее, чем для каждого, по крайней мере, в моем случае. Это связано с тем, что весь конвейер агрегации выполняется в процессе mongod, тогда как решение на основе find()
и insert()
должно отправлять все документы с сервера клиенту, а затем обратно. Это может привести к снижению производительности, даже если сервер и клиент находятся на одной машине.
Собственно, в MongoDB есть эквивалент SQL insert into ... select from
. Во-первых, вы конвертируете несколько документов в массив документов; то вы вставляете массив в целевую коллекцию
db.subset.insert(db.full_set.find({date:"20120105"}).toArray())
Наиболее общим решением является следующее:
Используйте агрегацию (ответ, заданный @melan):
db.full_set.aggregate({$match:{your query here...}},{$out:"sample"})
db.sample.copyTo("subset")
Это работает, даже когда перед операцией есть документы в "подмножестве", и вы хотите сохранить эти "старые" документы и просто вставить в нее новое подмножество.
Необходимо соблюдать осторожность, поскольку команда copyTo()
заменяет документы тем же _id
.
Нет прямого эквивалента SQL insert into ... select from ...
.
Ты должен сам позаботиться об этом. Извлеките интересующие документы и сохраните их в другой коллекции.
Вы можете сделать это в оболочке, но я бы использовал небольшой внешний script в Ruby. Что-то вроде этого:
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
Mongodb имеет агрегат и оператор $ out, которые позволяют сохранять подмножество в новой коллекции. Ниже приведены подробности:
$ out Принимает документы, возвращенные конвейером агрегации, и записывает их в указанную коллекцию.
Синтаксис:
{ $out: "<output-collection>" }
ПримерExample Коллекция книг содержит следующие документы:
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 }
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 }
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 }
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
Следующая операция агрегации поворачивает данные в коллекции книг на заголовки, сгруппированные по авторам, а затем записывает результаты в коллекцию авторов.
db.books.aggregate( [
{ $group : { _id : "$author", books: { $push: "$title" } } },
{ $out : "authors" }
] )
После операции собрание авторов содержит следующие документы:
{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
В заданном вопросе используйте следующий запрос, и вы получите новую коллекцию с именем 'col_20120105' в своей базе данных
db.products.aggregate([
{ $match : { date : "20120105" } },
{ $out : "col_20120105" }
]);