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 で動作します。Mongo が SQL と異なる点は、distinct の使用以外に大きな注意点が 1 つあります。サブドキュメントはバイナリ表現で比較されます (例を以下に示します)。そのため、Mongo での distinct の意味は、サブドキュメントの SQL 用語とは少し異なります。したがって {... , subdoc:[{a:1,b:1}]} {..., subdoc:[{b:1,a:1}]} は、subdoc の 2 つの異なる値を表します。これは、サブ文書の場合のみです。最上位フィールドは任意の順序にすることができます。さらに、Mongo は、配列を除き、ドキュメント内のフィールドの順序を保証しません。そのため、subdoc.a での集計は得られる結果を保証しますが (a 自体もサブドキュメントではないと仮定して)、subdoc.a での集計はそうではありません。

サブドキュメント フィールドをフィールド マップごとに比較する場合は、reduce を使用できます。複雑度マップの削減は、AF よりも数桁高くなります。MapReduce について読みたい場合: http://docs.mongodb.org/manual/core/map-reduce/

すべての免責事項と警告を確認したので、以下の AF シェル コマンドは、同じ ID を持つすべてのものを適切にカウントします: db.collection.aggregate({$unwind:"$list"}, {$group: {_id: "$list.id", count:{$sum:1}}}) このコマンドは、コレクション内の個別のドキュメントの数をリストで合計します。残念ながら、C ドライバーには集計ヘルパー コマンドがありません。集計を実行するには、mongo_run_command 関数を使用する必要があります。これはカーソルではなく bson ドキュメントのみを返すことができることに注意してください。したがって、結果はドキュメント サイズの制限 (Mongo 2.5.3、16 メガバイト) に制限されます。2 つの C の例は、全体としてサブドキュメントで合計されています。これは、全体として同等であるため、これらの順序付けが重要です。を追加する必要があります。

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;
}

最後になりましたが、シェルでデータベースに接続してから次のコマンドを実行すると、クエリを表示できます (データベースをコマンド ラインから直接起動し、フォークしなかった場合は、そのターミナルで表示できます)。

use admin
db.runCommand( { setParameter: 1, logLevel: 1 } )

これは、データベースに送信していると思われるコマンドをデバッグするのに役立ちます。その端末では、mongo シェルで作成したものと同じように見えるはずです。

うまくいけば、それはあなたの質問のすべての側面をカバーしています. 他に何か必要な場合はお知らせください。

ベスト、チャーリー

于 2013-09-17T19:08:46.477 に答える