2012-03-14 3 views

ответ

46

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

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

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

+5

Начиная с [2.2] (http://docs.mongodb.org/manual/reference/method/db.collection.insert/), вставка может принимать массив документов, поэтому вы можете выполнить команду var docs =. . ..find (...) ToArray(); db.coll.insert (документы) '. Я не нашел производительность очень хорошей в любом случае, хотя –

+1

К сожалению [$ out] (https://docs.mongodb.org/manual/reference/operator/aggregation/out/) пришел в Mongo с версии [2.6 ] (https://docs.mongodb.org/manual/release-notes/2.6/), а не [2.2] (https://docs.mongodb.org/manual/release-notes/2.2 /) – CroWell

4

Там нет прямого эквивалента в SQL insert into ... select from ....

Вы должны сами позаботиться об этом. Извлеките интересующие документы и сохраните их в другой коллекции.

Вы можете сделать это в оболочке, но я бы использовал небольшой внешний скрипт в 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 
13

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

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

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

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

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

+0

просто учитывайте, что он не удастся, если результат агрегирования превышает максимальный размер документа (16 МБ). – c24b

+5

$ out не имеет обычного ограничения на размер документа, поскольку вы пишете в коллекцию – Kyrstellaine

+0

. Дополнительные данные: я просто провел сравнение с моими собственными данными, а совокупность примерно в 50 раз быстрее, чем для каждого. Я также сравнивал с mapreduce, а совокупность примерно в 5 раз быстрее. – Luke

7

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

использование

Марка агрегации (ответ дается @melan):

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

Это работает даже при наличии документов в «подмножестве» до операции и вы хотите сохранить эти «старые» документы и просто вставить в него новое подмножество.

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

+0

Объяснение copyTo было очень полезным дополнением. – TheDude

Смежные вопросы