mongodb đếm số giá trị riêng biệt trên mỗi trường / khóa


104

Có một truy vấn để tính toán bao nhiêu giá trị riêng biệt mà một trường chứa trong DB.

fe Tôi có một trường cho quốc gia và có 8 loại giá trị quốc gia (Tây Ban Nha, Anh, Pháp, v.v.)

Nếu ai đó thêm nhiều tài liệu hơn với một quốc gia mới, tôi muốn truy vấn trả về 9.

Có cách nào dễ dàng hơn sau đó nhóm và đếm không?


2
Bạn đã nhìn vào khung tổng hợp chưa?
WiredPrairie


Câu trả lời:


197

MongoDB có một distinctlệnh trả về một mảng các giá trị riêng biệt cho một trường; bạn có thể kiểm tra độ dài của mảng để biết số lượng.

Cũng có một trình db.collection.distinct()trợ giúp trình bao :

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

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

47
điều này không thực sự hiệu quả nếu số lượng các giá trị khác biệt của bạn quá cao ... nếu bạn đang xem tên riêng biệt của những người trên thế giới hoặc một cái gì đó. bạn có câu trả lời có quy mô không?
underrun

3
1+ cho độ dài. tôi đã đấu tranh để tìm một cái gì đó như thế. Cảm ơn.
Adeel Ahmad

Tôi không biết tại sao họ đừng đếm sử dụng () đó là tốt
Marian Klühspies

1
@ MarianKlühspies - vì nó chỉ là một mảng javascript, sử dụng thuộc tính length để đếm số phần tử.
UpTheCreek

Đúng là những gì tôi đang tìm kiếm ... TY
Maulzey

113

Đây là ví dụ về việc sử dụng API tổng hợp. Để làm phức tạp trường hợp, chúng tôi đang nhóm các từ không phân biệt chữ hoa chữ thường từ thuộc tính mảng của tài liệu.

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

cho kết quả chẳng hạn như

{ "_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
Đăng nhập chỉ để + câu trả lời này. Cảm ơn! btw nếu bạn đang làm điều đó trên một trường duy nhất, chỉ cần xóa dòng thư giãn.
Richie Rich

@RichieRich, unwindlà cần thiết vì mã đang nhóm các giá trị riêng lẻ của một trường mảng phù hợp với cách distincthoạt động.
Paul

@Paul điều Richie đã nói là nếu việc nhóm được thực hiện chỉ là trường "thông thường" (chuỗi, int, v.v.) thì bạn không cần bước thư giãn. Không đúng sao?
guyarad

@guyarad unwindlà cần thiết khi làm việc với mảng.
Paul

+1 cho câu trả lời, chính xác là điều tôi đang làm, tuy nhiên sự khác biệt có sức hấp dẫn riêng nhưng đây chỉ là vàng :) - dù sao thì tôi cũng phải đọc thêm về tổng hợp để đạt được bộ kết quả mong muốn để lọc dữ liệu
Talha

21

Với MongoDb 3.4.4 và mới hơn, bạn có thể tận dụng việc sử dụng $arrayToObjecttoán tử và một $replaceRootđường dẫn để có được số lượng.

Ví dụ: giả sử bạn có một tập hợp người dùng với các vai trò khác nhau và bạn muốn tính tổng số các vai trò khác nhau. Bạn sẽ cần chạy đường dẫn tổng hợp sau:

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

Đầu ra mẫu

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

Đây không phải là câu trả lời cho câu hỏi, nhưng nó vẫn hữu ích. Tôi tự hỏi làm thế nào điều này thực hiện so với .distinct().
Redsandro

9

Bạn có thể tận dụng Tiện ích mở rộng của Mongo Shell . Đó là một lần nhập .js duy nhất mà bạn có thể thêm vào $HOME/.mongorc.jshoặc theo chương trình, nếu bạn cũng đang viết mã trong Node.js / io.js.

Mẫu vật

Đối với mỗi giá trị riêng biệt của trường sẽ đếm số lần xuất hiện trong tài liệu được lọc theo truy vấn tùy chọn

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

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

Tham số trường có thể là một mảng trường

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

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

làm cách nào để nhập cái này vào nút?
Salmaan P

require("./script.js"), tôi cho rằng
evandrix

đúng, nhưng tôi không thể nhận được các chức năng bên trong. Làm thế nào để tôi sử dụng chúng. Chúng được định nghĩa là db.protoptype.distinctAndCount
Salmaan P

Về cơ bản, có một phần hướng dẫn trong readme của repo (RTFM! 1 !! 1!), Hãy đặt .mongorc.jstệp vào nhà của bạn. Làm xong.
Janis F

6

Để tìm thấy sự khác biệt trong field_1bộ sưu tập nhưng chúng tôi cũng muốn có một số WHEREđiều kiện hơn chúng tôi có thể làm như sau:

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

Vì vậy, hãy tìm số khác biệt namesvới tập hợp có tuổi> 25 sẽ như sau:

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

Hy vọng nó giúp!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.