Mongo_count用于mongodb C驱动程序中的子文档

时间:2013-09-14 16:58:59

标签: mongodb bson mongodb-c

这是我的收藏的结构部分:

{
   ...
   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()函数不兼容。

1 个答案:

答案 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中创建的一样。

希望这涵盖了您问题的所有方面。如果您还有其他需要,请告诉我。

最佳, 查理