mongodb menghitung jumlah nilai yang berbeda per bidang / kunci

104

Apakah ada kueri untuk menghitung berapa banyak nilai berbeda yang berisi bidang di DB.

fe Saya memiliki bidang untuk negara dan ada 8 jenis nilai negara (spanyol, inggris, prancis, dll ...)

Jika seseorang menambahkan lebih banyak dokumen dengan negara baru, saya ingin kueri dikembalikan 9.

Apakah ada cara yang lebih mudah daripada mengelompokkan dan menghitung?

Liatz
sumber
2
Sudahkah Anda melihat kerangka agregasi ?
WiredPrairie
1
Atau pengurangan peta ?
WiredPrairie

Jawaban:

198

MongoDB memiliki distinctperintah yang mengembalikan larik nilai berbeda untuk sebuah bidang; Anda dapat memeriksa panjang array untuk menghitung.

Ada juga shell db.collection.distinct()helper:

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

> db.countries.distinct('country').length
4
Stennie
sumber
47
ini tidak benar-benar berfungsi jika jumlah nilai yang berbeda terlalu tinggi ... jika Anda melihat nama orang yang berbeda di dunia atau sesuatu. apakah Anda memiliki jawaban yang berskala?
underrun
3
1+ untuk panjangnya. saya berjuang untuk menemukan sesuatu seperti itu. Terima kasih.
Adeel Ahmad
Saya tidak tahu mengapa mereka tidak menggunakan count () di sana juga
Marian Klühspies
1
@ MarianKlühspies - karena ini hanya array javascript, yang menggunakan properti length untuk menghitung jumlah elemen.
UpTheCreek
Hanya apa yang saya cari ... TY
Maulzey
113

Berikut adalah contoh penggunaan API agregasi. Untuk memperumit kasus, kami mengelompokkan berdasarkan kata-kata yang tidak peka huruf besar / kecil dari properti array dokumen.

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

yang memberikan hasil seperti

{ "_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 }
ahli
sumber
2
Masuk hanya untuk + jawaban ini. Terima kasih! btw jika Anda melakukannya di bidang yang unik, hapus saja garis pelepas lelah.
Richie Rich
@RichieRich, unwinddiperlukan karena kode mengelompokkan nilai individual dari bidang array yang cocok dengan cara distinctkerjanya.
Paul
@Paul apa yang Richie katakan adalah jika pengelompokan dilakukan hanya bidang "biasa" (string, int dll) maka Anda tidak perlu langkah melepas. Benar bukan?
guyarad
@guyarad unwinddiperlukan saat bekerja dengan array.
Paul
+1 untuk jawabannya, persis seperti yang saya kerjakan, betapapun berbeda memiliki daya tariknya sendiri tetapi ini hanya emas :) - bagaimanapun saya harus membaca lebih lanjut tentang agregat untuk mencapai serangkaian hasil yang diinginkan untuk memfilter data
Talha
21

Dengan MongoDb 3.4.4 dan yang lebih baru, Anda dapat memanfaatkan penggunaan $arrayToObjectoperator dan $replaceRootpipeline untuk menghitungnya.

Misalnya, Anda memiliki kumpulan pengguna dengan peran berbeda dan Anda ingin menghitung jumlah peran yang berbeda. Anda perlu menjalankan pipeline agregat berikut:

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

Contoh Output

{
    "user" : 67,
    "superuser" : 5,
    "admin" : 4,
    "moderator" : 12
}
chridam
sumber
Ini bukanlah jawaban atas pertanyaan tersebut, tetapi tetap berguna. Saya bertanya-tanya bagaimana kinerjanya dibandingkan .distinct().
Redsandro
9

Anda dapat memanfaatkan Ekstensi Mongo Shell . Ini adalah impor .js tunggal yang dapat Anda tambahkan ke Anda $HOME/.mongorc.js, atau secara terprogram, jika Anda juga melakukan coding di Node.js / io.js.

Sampel

Untuk setiap nilai berbeda dari bidang menghitung kemunculan dalam dokumen secara opsional difilter berdasarkan kueri

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

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

Parameter bidang bisa berupa larik bidang

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

{
  "Austin,Educator" : 1,
  "Aurelia,Educator" : 1,
  "Augustine,Carpenter" : 1,
  ...
}
evandrix
sumber
bagaimana cara mengimpor ini di node?
Salmaan P
require("./script.js"), saya kira
evandrix
benar, tapi saya tidak bisa mendapatkan fungsi di dalamnya. Bagaimana cara menggunakannya. Mereka didefinisikan sebagai db.protoptype.distinctAndCount
Salmaan P
Ada bagian cara kerja di readme repo (RTFM! 1 !! 1!) Pada dasarnya, masukkan .mongorc.jsfile ke direktori home Anda. Selesai.
Janis F
6

Untuk menemukan perbedaan dalam field_1koleksi tetapi kami menginginkan beberapa WHEREkondisi juga daripada yang dapat kami lakukan seperti berikut:

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

Jadi, cari nomor yang berbeda namesdari koleksi di mana usia> 25 akan seperti:

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

Semoga membantu!

Vimal
sumber