这是我的收藏的结构部分:
{
...
list: [
{ id:'00A', name:'None 1' },
{ id:'00B', name:'None 2' },
],
...
}
使用“distinct”功能后(参见链接:sub-object in sub-array in mongodb-C)
对于我来说,计算子文档数量的最佳解决方案是什么?
因为使用mongo_count与distinct和mongo_run_command()函数不兼容。
答案 0 :(得分:1)
如果您在问题中包含更多信息,例如您正在使用的版本以及您的总体目标,那将会很有帮助。 Mongo是特定于用例的。 我知道你正在寻找数组中不同元素的数量。当涉及数组时,聚合框架[AF]通常是完成任务的最简单方法(遗憾的是,此时您可能还需要使用map reduce来处理更复杂的查询)。 您应该根据具体情况修改以下示例。此示例适用于C驱动程序0.8和mongodb 2.4.6。 除了使用distinct之外,Mongo还有一个不同于SQL的警告。子文档在二进制表示中进行比较(下面的示例)。所以Mongo中distinct的含义与子文档的SQL术语略有不同。因此 {...,subdoc:[{a:1,b:1}]} {...,subdoc:[{b:1,a:1}]} 表示subdoc的两个不同值。这只是子文档的情况;顶级字段可以按任何顺序排列。此外,除数组外,Mongo不保证文档中的字段顺序。因此,虽然subdoc.a上的聚合将保证您获得的结果(假设它本身也不是一个子文档),但在subdoc上的聚合不会。
如果要通过字段映射比较一个subdoc字段,可以使用reduce。复杂性图减少比AF高几个数量级。如果您想了解MapReduce:http://docs.mongodb.org/manual/core/map-reduce/
现在我们已经完成了所有的disclamers和警告:下面的AF shell命令将使用相同的ID正确计算所有内容: db.collection.aggregate({$ unwind:“$ list”},{$ group:{_ id:“$ list.id”,count:{$ sum:1}}}) 此命令按列表汇总集合中不同文档的数量。 不幸的是,C驱动程序没有聚合助手命令。需要使用mongo_run_command函数来运行聚合。请注意,这只能返回bson文档而不是光标;因此结果仅限于文档大小限制(Mongo 2.5.3,16Megs)。 对于这些排序问题,两个C示例总结了subdoc,作为一个整体用于相同的目的。你需要添加 。 到subdoc获取一个特定的字段(也不能是一个子字段,或者你已经说明了相同的约束)。
以下是使用BCON(http://api.mongodb.org/c/current/bcon.html)的示例,这是一种易于使用的推荐方法(比例2慢约10%):
#include <mongo.h>
#include <bcon.h>
#include <stdio.h>
int main() {
/*
* We assume objects in the form of {_id:<any_id>, list:[{a:<int>,b:<int>}, ...]}
*/
char table[] = "agg";
mongo conn[1];
mongo_init(conn);
if(MONGO_OK != mongo_client(conn, "127.0.0.1", 27017))
return 1;
bson b[1], b_result[1];
/*create the aggregation command in bson*/
bcon cmd_aggregate[] = { "aggregate", BRS(table),
"pipeline",
"[",
"{",
"$unwind", "$list",
"}",
"{",
"$group",
"{",
"_id", "$list",
"distinct_count",
"{",
"$sum", BI(1),
"}",
"}",
"}",
"]",
BEND
};
bson_from_bcon(b, cmd_aggregate);
/*So you can see your command*/
bson_print(b);
/*run the command*/
mongo_run_command(conn, "test", b, b_result);
/*command results*/
bson_print(b_result);
bson_destroy(b_result);
bson_destroy(b);
mongo_destroy(conn);
return 0;
}
这是稍微快一点的风格:
#include <mongo.h>
#include <stdio.h>
int main() {
/*
* We assume objects in the form of {_id:<any_id>, list:[{a:<int>,b:<int>}, ...]}
*/
char table[] = "agg";
mongo conn[1];
mongo_init(conn);
if(MONGO_OK != mongo_client(conn, "127.0.0.1", 27017))
return 1;
bson b[1], b_result[1];
/*create the aggregation command in bson*/
bson_init(b);
bson_append_string(b, "aggregate", "agg");
bson_append_start_array(b, "pipeline");
bson_append_start_object(b,"0");
bson_append_string(b, "$unwind", "$list");
bson_append_finish_object(b);
bson_append_start_object(b,"1");
bson_append_start_object(b,"$group");
bson_append_string(b,"_id", "$list");
bson_append_start_object(b, "_count");
bson_append_int(b, "$sum", 1);
bson_append_finish_object(b);
bson_append_finish_object(b);
bson_append_finish_object(b);
bson_append_finish_array(b);
bson_finish(b);
/*So you can see your command*/
bson_print(b);
/*run the command*/
mongo_run_command(conn, "test", b, b_result);
/*command results*/
bson_print(b_result);
bson_destroy(b_result);
bson_destroy(b);
mongo_destroy(conn);
return 0;
}
最后但并非最不重要的是,在shell中连接数据库然后运行以下命令将允许您查看查询(如果您直接从命令行启动数据库并且没有分叉它,您可以在其中看到它们终端):
use admin
db.runCommand( { setParameter: 1, logLevel: 1 } )
这对于调试您认为要发送到数据库的命令很有用。它应该在那个终端中看起来和你在mongo shell中创建的一样。
希望这涵盖了您问题的所有方面。如果您还有其他需要,请告诉我。
最佳, 查理