0

Mongoにコレクションがあり、usersこの map reduce を実行します。これは、 COUNT(*) GROUP BY と同等であると考えていますorigin

> m = function() { for (i in this.membership) {
... emit( this.membership[i].platform_profile.origin, 1 );
... }  }
function () {
    for (i in this.membership) {
        emit(this.membership[i].platform_profile.origin, 1);
    }
}
> r = function( id, values ) { var result = 0; 
... for ( var i = 0; i < values.length; i ++ ) { result += values[i];  }
... return result; }
function (id, values) {
    var result = 0;
    for (var i = 0; i < values.length; i++) {
        result += values[i];
    }
    return result;
}
> db.users.mapReduce(m, r, {out : { inline: 1}});
{
    "results" : [
        {
            "_id" : 0,
            "value" : 15
        },
        {
            "_id" : 1,
            "value" : 449
        },
    ...
}

しかし、このフィールドが のような特定の値に設定されているドキュメントの数を数えようとすると1、得られる結果は少なくなります。

db.users.count({"membership.platform_profile.origin": 1});

424

私は何が欠けていますか?

4

3 に答える 3

2

カウント クエリでスパース インデックスを使用していませんか? 私の唯一の推測では、他のクエリ基準により、インデックスにないドキュメントがカウントから無視された場合があります。

いくつかのフィクスチャ データを使用してスキーマを再作成しました。map/reduce クエリと単純なカウント クエリの結果は一致しています。

db.users.drop();

var map = function() {
    for (i in this.membership) {
        emit(this.membership[i].platform_profile.origin, 1);
    }
};

var reduce = function(id, values ) {
    var result = 0;
    for (var i = 0; i < values.length; i++) {
        result += values[i];
    }
    return result;
}

var origins = {1: "a", 2: "b", 3: "c", 4: "d"};

for (var i = 0; i < 1000; ++i) {
    var membership = [];

    for (var o in origins) {
        if (0 == i % o) {
            membership.push({ platform_profile: { origin: origins[o] }});
        }
    }

    db.users.save({ membership: membership });
}

db.users.mapReduce(map, reduce, {out: {inline: 1}}).results.forEach(function(result){
    print(result["_id"] + ": " + result["value"]);
});

for (var o in origins) {
    print(origins[o] + ": " + db.users.count({"membership.platform_profile.origin": origins[o]}));
}

出力は次のとおりです。

$ mongo --quiet mr_count.js 
a: 1000
b: 500
c: 334
d: 250
a: 1000
b: 500
c: 334
d: 250
于 2012-07-10T19:51:00.080 に答える
1

次の map/reduce を同等のものとして使用できます。COUNT(*) GROUP BY origin

マップ/リデュース関数:

map = function() {
    if(!this.membership) return;

    for (i in this.membership) {
        if(!this.membership[i].platform_profile || !this.membership[i].platform_profile.origin) return;
        emit(this.membership[i].platform_profile.origin, 1);
    }
}

reduce = function(key, values) {
    var count = 0;

    for (v in values) {
        count += values[v];
    }
    return count;
}

result = db.runCommand({
        "mapreduce" : "users", 
        "map" : map,
        "reduce" : reduce,
        "out" : "users_count"
});
于 2012-07-09T08:48:45.633 に答える