0

这是我收藏的结构部分:

{
   ...
   list: [
      { id:'00A', name:'None 1' },
      { id:'00B', name:'None 2' },
   ],
   ...
}

在使用了函数“distinct”之后(参见链接:mongodb-C 中的子数组中的子对象

请问我计算子文件数量的最佳解决方案是什么?

因为 mongo_count 的使用与 distinct 和 mongo_run_command() 函数不兼容。

4

1 回答 1

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 上的聚合将保证您获得的结果(假设 a 本身也不是子文档),但 subdoc 上的聚合不会。

如果要按字段映射减少子文档字段,可以使用。复杂度图减少比 AF 高几个数量级。如果您想了解 MapReduce:http ://docs.mongodb.org/manual/core/map-reduce/

现在我们已经了解了所有的声明和警告:下面的 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 上求和,作为一个整体用于相等目的,因此对于这些排序问题。您需要添加 .

这是使用 BCON 的示例(http://api.mongodb.org/c/current/bcon.html),推荐的易于使用的方法(它比示例二慢 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 中创建的相同。

希望这涵盖了您问题的所有方面。需要帮助请叫我。

最好的,查理

于 2013-09-17T19:08:46.477 回答