2012-03-14 248 views
43

我有一組像這樣保存子集另一個集合

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

我如何保存日期「20120105」到另一個收集這些文件的一個子集?

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

回答

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/),insert可以接受一系列文檔,因此您可以執行'var docs =。 。..find(...)指定者(); db.coll.insert(文檔)'。儘管 – 2013-03-01 02:58:45

+1

不幸,[$ out](https://docs.mongodb.org/manual/reference/operator/aggregation/out/)自從版本2.6 [ ](https://docs.mongodb.org/manual/release-notes/2.6/),而不是[2.2](https://docs.mongodb.org/manual/release-notes/2。2 /) – CroWell 2015-11-11 11:01:31

4

有SQL的insert into ... select from ...沒有直接的等價物。

你必須自己照顧它。獲取感興趣的文檔並將其保存到另一個集合中。

你可以在shell中做到這一點,但我會在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

作爲一個新的解決方案,我會建議使用聚合框架問題:

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

它比的forEach快大約100倍,至少在我的情況。這是因爲整個聚合管道在mongod進程中運行,而基於find()insert()的解決方案必須將所有文檔從服務器發送到客戶端,然後再發回。即使服務器和客戶端在同一臺計算機上,性能也會受到影響。

+0

只是考慮到如果聚合結果超過最大文檔大小(16MB),將會失敗 – c24b 2015-05-19 15:19:12

+5

$ out對文檔大小沒有通常的限制,因爲您正在寫入集合 – Kyrstellaine 2015-05-29 22:31:16

+0

進一步的證據:我只是與我自己的數據進行比較,聚合速度比forEach快大約50倍。我還比較了mapreduce,聚合速度快了大約5倍。 – Luke 2016-02-09 15:35:27

7

最通用的解決方案是這樣的:

製作使用(由@melan給出的答案)的聚合:

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

在有手術前的「子集」文件,這甚至工作你想保留那些「舊」的文檔,只是插入一個新的子集。

必須小心,因爲copyTo()命令用相同的_id替換文檔。

+0

copyTo的解釋是非常有用的補充。 – TheDude 2017-06-15 15:02:58