MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Tổng hợp MongoDB Mỗi khóa trên một tài liệu con

Như đã nêu, không thể xử lý các tài liệu như thế này với khung tổng hợp trừ khi bạn thực sự sẽ cung cấp tất cả các khóa, chẳng hạn như:

db.events.aggregate([
   { "$group": {
       "_id": "$app_id",
       "event_count": { "$sum": "$event_count" },
       "0": { "$sum": "$event_count_per_type.0" },
       "10": { "$sum": "$event_count_per_type.10" }
       "20": { "$sum": "$event_count_per_type.20" }
       "30": { "$sum": "$event_count_per_type.30" }
   }}
])

Nhưng tất nhiên bạn phải chỉ định rõ ràng mọi chìa khóa bạn muốn làm việc trên. Điều này đúng với cả khung tổng hợp và các hoạt động truy vấn chung trong MongoDB, vì để truy cập các phần tử được ghi chú trong biểu mẫu "tài liệu con" này, bạn cần chỉ định "đường dẫn chính xác" đến phần tử để thực hiện bất kỳ điều gì với nó.

Khung tổng hợp và các truy vấn chung không có khái niệm "truyền tải", có nghĩa là chúng không thể xử lý "từng khóa" của một tài liệu. Điều đó yêu cầu cấu trúc ngôn ngữ để thực hiện điều đó không được cung cấp trong các giao diện này.

Nói chung, mặc dù vậy, việc sử dụng "tên khóa" làm điểm dữ liệu nơi tên của nó thực sự đại diện cho "giá trị" là một chút "phản mẫu". Cách tốt hơn để mô hình hóa điều này sẽ là sử dụng một mảng và đại diện cho "loại" của bạn dưới dạng một giá trị của chính nó:

{
    "app_id": "DHJFK67JDSJjdasj909",
    "date: ISODate("2014-08-07T00:00:00.000Z"),
    "event_count": 32423,
    "events": [
        { "type": 0,  "value": 322  },
        { "type": 10, "value": 4234 },
        { "type": 20, "value": 653  },
        { "type": 30, "value": 7562 }
    ]
}

Cũng lưu ý rằng "ngày tháng" bây giờ là một đối tượng ngày tháng thích hợp chứ không phải là một chuỗi, đây cũng là điều mà thực tiễn tốt nên làm. Mặc dù vậy, loại dữ liệu này rất dễ xử lý với khung tổng hợp:

db.events.aggregate([
    { "$unwind": "$events" },
    { "$group": {
        "_id": { 
            "app_id": "$app_id",
            "type": "$events.type"
        },
        "event_count": { "$sum": "$event_count" },
        "value": { "$sum": "$value" }
    }},
    { "$group": {
        "_id": "$_id.app_id",
        "event_count": { "$sum": "$event_count" },
        "events": { "$push": { "type": "$_id.type", "value": "$value" } }
    }}
]) 

Điều đó cho thấy nhóm hai giai đoạn mà trước tiên lấy tổng cho mỗi "loại" mà không chỉ định từng "khóa" vì bạn không còn phải làm như vậy nữa, sau đó trả về dưới dạng một tài liệu duy nhất cho mỗi "app_id" với kết quả trong một mảng như chúng đã được lưu trữ ban đầu. Biểu mẫu dữ liệu này thường linh hoạt hơn nhiều để xem xét một số "loại" hoặc thậm chí "giá trị" trong một phạm vi nhất định.

Trường hợp bạn không thể thay đổi cấu trúc thì lựa chọn duy nhất của bạn là mapReduce. Điều này cho phép bạn "mã hóa" việc truyền tải các khóa, nhưng vì điều này yêu cầu diễn giải và thực thi JavaScript nên nó không nhanh như khung tổng hợp:

db.events.mapReduce(
    function() {
        emit(
            this.app_id,
            {
                "event_count": this.event_count,
                "event_count_per_type": this.event_count_per_type
            }
        );
    },
    function(key,values) {

        var reduced = { "event_count": 0, "event_count_per_type": {} };

        values.forEach(function(value) {
            for ( var k in value.event_count_per_type ) {
                if ( !redcuced.event_count_per_type.hasOwnProperty(k) )
                    reduced.event_count_per_type[k] = 0;
                reduced.event_count_per_type += value.event_count_per_type;
            }
            reduced.event_count += value.event_count;
        })
    },
    {
        "out": { "inline": 1 }
    }
)

Điều đó về cơ bản sẽ đi qua và kết hợp các "khóa" và tổng hợp các giá trị cho mỗi một khóa được tìm thấy.

Vì vậy, bạn có một trong hai lựa chọn:

  1. Thay đổi cấu trúc và làm việc với các truy vấn chuẩn và tổng hợp.
  2. Giữ nguyên cấu trúc và yêu cầu xử lý JavaScript và mapReduce.

Nó phụ thuộc vào nhu cầu thực tế của bạn, nhưng trong hầu hết các trường hợp, việc tái cấu trúc mang lại lợi ích.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Cách quản lý cơ sở dữ liệu lớn một cách hiệu quả

  2. C # - MongoDB - Cập nhật một phần tử bên trong Tài liệu lồng nhau

  3. Xác thực MongoDB-CR không thành công

  4. Làm cách nào để kiểm tra xem một trường mảng có phải là một phần của một mảng khác trong MongoDB hay không?

  5. Viết nhật ký MongoDB có đảm bảo độ bền không?