2014-02-09 125 views
1

文檔:的MongoDB - 執行子查詢

{ "_id":1, "id":1, "list" : [ { "lv" : 1 , "id":1}, {"lv" : 2 , "id":2} ] } 

我想確實發現({ 「_ ID」:1},{ 「ID」:1, 「list.lv」:1}),但限制{」 list.lv「:1}並附加一個條件:」list.id = id「。這意味着我只想檢索列表中第一個元素的「id」和「list.lv」部分,因爲它的「list.id」==「id」== 1

通常情況下,代碼中提供的條件值,但在本例中,該值在文檔中。 SQL通過子查詢或連接表執行此操作。 mongodb是否支持單個查詢?以及如何在C++驅動程序中編寫它?

根據答案,將C++代碼:

mongo::BSONObj res; 
std::vector<mongo::BSONObj> pipeline; 
pipeline.push_back(BSON("$match"<<BSON("_id"<<1))); 
pipeline.push_back(BSON("$unwind"<<"$list")); 
mongo::BSONArrayBuilder ab; 
ab<<"$id"<<"$list.id"; 
pipeline.push_back(BSON("$project"<<BSON("id"<<1<<"list.lv"<<1<<"equalsFlag"<<BSON("$subtract"<<ab.arr())))); 
pipeline.push_back(BSON("$match"<<BSON("equalsFlag"<<0))); 
pipeline.push_back(BSON("$project"<<BSON("id"<<1<<"list.lv"<<1))); 
conn->runCommand("db_name", BSON("aggregate" << "collection_name" << "pipeline" << pipeline), res); 
std::cout<<res["result"].Array()[0].Obj().getObjectField("list").getIntField("lv"); 

回答

1

,如果我得到你的問題試試這個本地aggregate framework查詢來完成你所需要的:

db.collectionName.aggregate(
{"$match" : {"_id" : 1 }}, 
{"$unwind" : "$list"}, 
{"$project" : {"id":1, "list.lv" : 1, "equalsFlag" : {"$subtract" : ["$id", "$list.id"]}}}, 
{"$match" : {"equalsFlag" : 0}}, 
{"$project" : {"id": 1, "list.lv" : 1}}) 

讓我把解釋詳情。首先儘可能多地過濾文件是很重要的。我們可以用第一個$match來做到這一點。請注意,如果我們在流水線結束處執行{「_id」:1}過濾器,mongo將無法使用索引。 $unwind會將每個列表數組元素轉換爲單獨的文檔。然後我們需要比較兩個字段。我沒有意識到除$where之外的任何簡單方法,但我們不能將它用於聚合框架。好在雙方IDlist.id是數字,所以我們可以$減去一個從另一個,看看他們是平等的,「equalsFlag」:{「$減」:「$ ID」,「$列表。 ID」]} 。如果是這樣,equalsFlag將爲0。所以我們只需要添加一個新的$匹配拿到文件,其中ID = list.id最後將其從結果中省略equalsFlag領域,我們多了一個$項目。

我不是C++的人,但我確信C++驅動程序支持聚合框架作爲大多數其他驅動程序。所以,只需谷歌的一些例子將這個本地查詢轉換爲一個C++。這應該是相當容易的,至少對C#來說是這樣。

編輯:從牛仔 C++代碼來完成答案

mongo::BSONObj res; 
std::vector<mongo::BSONObj> pipeline; 
pipeline.push_back(BSON("$match"<<BSON("_id"<<1))); 
pipeline.push_back(BSON("$unwind"<<"$list")); 
mongo::BSONArrayBuilder ab; 
ab<<"$id"<<"$list.id"; 
pipeline.push_back(BSON("$project"<<BSON("id"<<1<<"list.lv"<<1<<"equalsFlag"<<BSON("$subtract"<<ab.arr())))); 
pipeline.push_back(BSON("$match"<<BSON("equalsFlag"<<0))); 
pipeline.push_back(BSON("$project"<<BSON("id"<<1<<"list.lv"<<1))); 
conn->runCommand("db_name", BSON("aggregate" << "collection_name" << "pipeline" << pipeline), res); 
std::cout<<res["result"].Array()[0].Obj().getObjectField("list").getIntField("lv"); 

希望它能幫助!

+0

我工作。我還在我的問題中添加了C++驅動程序代碼。 – jean

+0

當然可以。完成! –