c++ - mongodb - 执行子查询

标签 c++ mongodb

文档:

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

我想做 find({"_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");

最佳答案

如果我有问题,请尝试使用 native 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 都是数字,所以我们可以$subtract 一个从另一个看它们是否相等,“equalsFlag”:{ "$subtract": ["$id", "$list.id"]} 。如果是,equalsFlag 将为 0。所以我们只需添加一个新的 $match 来获取 id=list.id 的文档,最后到从结果中省略 equalsFlag 字段,我们还有一个 $project。

我不是 C++ 专家,但我确信 C++ 驱动程序像大多数其他驱动程序一样支持聚合框架。因此,只需谷歌一些示例即可将此 native 查询转换为 C++ 查询。这应该相当容易,至少对于 C# 来说是这样。

编辑:来自 jean 的 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");

希望对您有所帮助!

关于c++ - mongodb - 执行子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21661416/

相关文章:

c++ - 如何在 CTreeCtrl 中显示自定义工具提示?

c++ - 线性PCM 16位至8位

c++ - 一劳永逸地理解 C 和 C++ 中 f() 和 f(void) 之间的区别

arrays - 使用node、express将对象数组保存到mongo数据库

MongoDB:如何在聚合上应用多个 $project

c++ - C++ 中的流畅接口(interface)和继承

c++ - 如何将 char 转换为关联的转义序列?

javascript - MongoDB 数组在数据库中变成了字符串

node.js - 在mongoDB中分页搜索结果

multithreading - `foreach` 过度并行收集永远不会开始