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?


2
Sudahkah Anda melihat kerangka agregasi ?
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

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 }

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
}

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,
  ...
}

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!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.