Подтвердить что ты не робот

Сохранить подмножество коллекции MongoDB в другой коллекции

У меня есть такой набор

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

Как сохранить подмножество этих документов с датой '20120105' в другую коллекцию?

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

4b9b3361

Ответ 1

Вот версия оболочки:

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

Примечание: Начиная с MongoDB 2.6, структура агрегации позволяет делать это быстрее; см. мелан ответ для деталей.

Ответ 2

В качестве более нового решения я бы посоветовал использовать структуру Aggregation для проблемы:

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

Он работает примерно в 100 раз быстрее, чем для каждого, по крайней мере, в моем случае. Это связано с тем, что весь конвейер агрегации выполняется в процессе mongod, тогда как решение на основе find() и insert() должно отправлять все документы с сервера клиенту, а затем обратно. Это может привести к снижению производительности, даже если сервер и клиент находятся на одной машине.

Ответ 3

Собственно, в MongoDB есть эквивалент SQL insert into ... select from. Во-первых, вы конвертируете несколько документов в массив документов; то вы вставляете массив в целевую коллекцию

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

Ответ 4

Наиболее общим решением является следующее:

Используйте агрегацию (ответ, заданный @melan):

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

Это работает, даже когда перед операцией есть документы в "подмножестве", и вы хотите сохранить эти "старые" документы и просто вставить в нее новое подмножество.

Необходимо соблюдать осторожность, поскольку команда copyTo() заменяет документы тем же _id.

Ответ 5

Нет прямого эквивалента 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

Ответ 6

Mongodb имеет агрегат и оператор $ out, которые позволяют сохранять подмножество в новой коллекции. Ниже приведены подробности:

$ out Принимает документы, возвращенные конвейером агрегации, и записывает их в указанную коллекцию.

  • Операция $ out создает новую коллекцию в текущей базе данных, если она еще не существует.
  • Коллекция не видна, пока агрегация не завершится.
  • В случае сбоя агрегации MongoDB не создает коллекцию.

Синтаксис:

{ $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" }
]);