mongodbは、フィールド/キーごとに異なる値の数を数えます


104

DBでフィールドに含まれる個別の値の数を計算するクエリはありますか?

fe国のフィールドがあり、国の値には8種類あります(スペイン、イギリス、フランスなど)。

誰かが新しい国のドキュメントをさらに追加した場合、クエリは9を返します。

グループ化してカウントするより簡単な方法はありますか?


2
集計フレームワークを見たことはありますか?
WiredPrairie 2013


インデックス付きの列MongoDBのselect count(distinct x)が重複している可能性があります-大きなデータセットの一意の結果。私はそこに私の答えを投稿しました。
エキスパート

回答:


197

MongoDBには distinctフィールドの個別の値の配列を返すコマンドがあります。配列の長さをカウントで確認できます。

シェルdb.collection.distinct()ヘルパーもあります。

> db.countries.distinct('country');
[ "Spain", "England", "France", "Australia" ]

> db.countries.distinct('country').length
4

47
個別の値の数が多すぎる場合、これは実際には機能しません...世界中の人々の個別の名前などを見ている場合。スケールする答えはありますか?
2014年

3
長さは1+。私はそのようなものを見つけるのに苦労していました。ありがとう。
Adeel Ahmad 2015

なぜそこでcount()も使用しないのか分かりません
MarianKlühspies15年

1
@MarianKlühspies-要素の数を数えるためにlengthプロパティを使用する単なるjavascript配列だからです。
UpTheCreek

ちょうど私が探していたもの... TY
Maulzey

113

集約APIの使用例です。ケースを複雑にするために、ドキュメントの配列プロパティから大文字と小文字を区別しない単語でグループ化しています。

db.articles.aggregate([
    {
        $match: {
            keywords: { $not: {$size: 0} }
        }
    },
    { $unwind: "$keywords" },
    {
        $group: {
            _id: {$toLower: '$keywords'},
            count: { $sum: 1 }
        }
    },
    {
        $match: {
            count: { $gte: 2 }
        }
    },
    { $sort : { count : -1} },
    { $limit : 100 }
]);

そのような結果を与える

{ "_id" : "inflammation", "count" : 765 }
{ "_id" : "obesity", "count" : 641 }
{ "_id" : "epidemiology", "count" : 617 }
{ "_id" : "cancer", "count" : 604 }
{ "_id" : "breast cancer", "count" : 596 }
{ "_id" : "apoptosis", "count" : 570 }
{ "_id" : "children", "count" : 487 }
{ "_id" : "depression", "count" : 474 }
{ "_id" : "hiv", "count" : 468 }
{ "_id" : "prognosis", "count" : 428 }

2
+この回答にログインしました。ありがとう!ところで、一意のフィールドでそれを実行している場合は、単にunwind行を削除してください。
リッチーリッチ

@RichieRich unwindは、コードが配列フィールドの個々の値をグループ化するために必要distinctです。
ポール

@Paulリッチーが言ったのは、グループ化が「通常の」フィールド(文字列、intなど)だけで行われる場合は、巻き戻しステップは必要ないということです。正しいですか?
Guyarad、

@guyarad unwindは配列を操作するときに必要です。
Paul

答えの+1、正確に私が取り組んでいたものですが、明確には独自の魅力がありますが、これは単なる金です:)-とにかく、データをフィルタリングするために必要な結果セットを達成するには、集計についてもっと読む必要があります
Talha

21

MongoDb 3.4.4以降では、$arrayToObject演算子と$replaceRootパイプラインの使用を活用してカウントを取得できます。

たとえば、さまざまな役割を持つユーザーのコレクションがあり、役割の個別の数を計算するとします。次の集計パイプラインを実行する必要があります。

db.users.aggregate([
    { "$group": {
        "_id": { "$toLower": "$role" },
        "count": { "$sum": 1 }
    } },
    { "$group": {
        "_id": null,
        "counts": {
            "$push": { "k": "$_id", "v": "$count" }
        }
    } },
    { "$replaceRoot": {
        "newRoot": { "$arrayToObject": "$counts" }
    } }    
])

出力例

{
    "user" : 67,
    "superuser" : 5,
    "admin" : 4,
    "moderator" : 12
}

これは質問に対する回答ではありませんが、それでも役に立ちます。これはと比べてどのように機能するのでしょうか.distinct()
Redsandro

9

Mongo Shell Extensionsを活用できます。$HOME/.mongorc.jsNode.js / io.jsでコーディングしている場合は、に追加したり、プログラムで追加したりできる単一の.jsインポートです。

サンプル

フィールドの個別の値ごとに、オプションでクエリでフィルタリングされたドキュメント内の出現回数をカウントします

> db.users.distinctAndCount('name', {name: /^a/i})

{
  "Abagail": 1,
  "Abbey": 3,
  "Abbie": 1,
  ...
}

フィールドパラメータはフィールドの配列にすることができます

> db.users.distinctAndCount(['name','job'], {name: /^a/i})

{
  "Austin,Educator" : 1,
  "Aurelia,Educator" : 1,
  "Augustine,Carpenter" : 1,
  ...
}

これをノードにインポートするにはどうすればよいですか?
Salmaan P 2017

require("./script.js")、私は思います
evandrix '06 / 11/17

右ですが、関数を内部に取り込むことができませんでした。どうやって使うの?それらは、db.protoptype.distinctAndCountとして定義されています
Salmaan P

リポジトリのreadme(RTFM!1 !! 1!)にハウツーセクションがあり.mongorc.jsます。基本的には、ファイルをホームディレクトリに置きます。できました。
Janis F

6

field_1コレクション内で明確に見つけるために、WHERE次のようにできるよりもいくつかの条件が必要です。

db.your_collection_name.distinct('field_1', {WHERE condition here and it should return a document})

したがって、names年齢が25歳以上のコレクションとは異なる数を見つけます。

db.your_collection_name.distinct('names', {'age': {"$gt": 25}})

それが役に立てば幸い!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.