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

Mongo / Mongoose - Tổng hợp theo ngày

Một cách tiếp cận tốt sẽ là chia đường ống tổng hợp thành nhiều bước với mục đích tính toán tổng hợp với từng nhóm, tức là tổng hợp hàng năm, hàng tháng và hàng tuần.

Tôi đã thực hiện một nỗ lực yếu ớt trong việc tạo ra đường dẫn đã nói nhưng không chắc liệu đó có phải là điều bạn đang theo đuổi hay không nhưng có thể cung cấp cho bạn một số dẫn đến một giải pháp, tốt hơn là một giải pháp tối ưu. Có lẽ ai đó có thể đưa ra câu trả lời tốt hơn.

Hãy xem xét những điều sau chưa được kiểm tra đường ống:

db.statements.aggregate([
    {
        "$group": {
            "_id": {
                "name": "$name",
                "year": { "$year": "$date" },
                "month": { "$month": "$date" },
                "week": { "$week": "$date" }
            },
            "total": { "$sum": "$amount" }
        }
    },
    {
        "$group": {
            "_id": {
                "name": "$_id.name",
                "year": "$_id.year"
            },
            "YearlySpends": { "$push": "$total" },
            "totalYearlyAmount": { "$sum": "$total" },
            "data": { "$push": "$$ROOT" }
        }
    },
    { "$unwind": "$data" },
    {
        "$group": {
            "_id": {
                "name": "$_id.name",
                "month": "$data._id.month"
            },
            "YearlySpends": { "$first": "$YearlySpends" },
            "totalYearlyAmount": { "$first": "$totalYearlyAmount" },
            "MonthlySpends": { "$push": "$data.total" },
            "totalMonthlyAmount": { "$sum": "$data.total" },
            "data": { "$push": "$data" }
        }
    },
    { "$unwind": "$data" },
    {
        "$group": {
            "_id": {
                "name": "$_id.name",
                "week": "$data._id.week"
            },
            "YearlySpends": { "$first": "$YearlySpends" },
            "totalYearlyAmount": { "$first": "$totalYearlyAmount" },
            "MonthlySpends": { "$first": "$MonthlySpends" },
            "totalMonthlyAmount": { "$first": "$totalMonthlyAmount" },
            "WeeklySpends": { "$push": "$data.total" },
            "totalWeeklyAmount": { "$sum": "$data.total" },
            "data": { "$push": "$data" }
        }
    },
    { "$unwind": "$data" },
    {
        "$group": {
            "_id": "$data._id",
            "YearlySpends": { "$first": "$YearlySpends" },
            "totalYearlyAmount": { "$first": "$totalYearlyAmount" },
            "MonthlySpends": { "$first": "$MonthlySpends" },
            "totalMonthlyAmount": { "$first": "$totalMonthlyAmount" },
            "WeeklySpends": { "$first": "$WeeklySpends" },
            "totalWeeklyAmount": { "$first": "$totalWeeklyAmount" }
        }
    }
])

Đầu ra mẫu

/* 1 */
{
    "_id" : {
        "name" : "Tesco",
        "year" : 2017,
        "month" : 3,
        "week" : 11
    },
    "YearlySpends" : [ 
        -3.3
    ],
    "totalYearlyAmount" : -3.3,
    "MonthlySpends" : [ 
        -3.3
    ],
    "totalMonthlyAmount" : -3.3,
    "WeeklySpends" : [ 
        -3.3
    ],
    "totalWeeklyAmount" : -3.3
}

/* 2 */
{
    "_id" : {
        "name" : "RINGGO",
        "year" : 2017,
        "month" : 4,
        "week" : 17
    },
    "YearlySpends" : [ 
        -3.3, 
        -26.3, 
        -33.3
    ],
    "totalYearlyAmount" : -62.9,
    "MonthlySpends" : [ 
        -33.3
    ],
    "totalMonthlyAmount" : -33.3,
    "WeeklySpends" : [ 
        -33.3
    ],
    "totalWeeklyAmount" : -33.3
}

/* 3 */
{
    "_id" : {
        "name" : "RINGGO",
        "year" : 2017,
        "month" : 3,
        "week" : 12
    },
    "YearlySpends" : [ 
        -3.3, 
        -26.3, 
        -33.3
    ],
    "totalYearlyAmount" : -62.9,
    "MonthlySpends" : [ 
        -3.3, 
        -26.3
    ],
    "totalMonthlyAmount" : -29.6,
    "WeeklySpends" : [ 
        -3.3
    ],
    "totalWeeklyAmount" : -3.3
}

/* 4 */
{
    "_id" : {
        "name" : "RINGGO",
        "year" : 2017,
        "month" : 3,
        "week" : 11
    },
    "YearlySpends" : [ 
        -3.3, 
        -26.3, 
        -33.3
    ],
    "totalYearlyAmount" : -62.9,
    "MonthlySpends" : [ 
        -3.3, 
        -26.3
    ],
    "totalMonthlyAmount" : -29.6,
    "WeeklySpends" : [ 
        -26.3
    ],
    "totalWeeklyAmount" : -26.3
}

/* 5 */
{
    "_id" : {
        "name" : "Sky",
        "year" : 2017,
        "month" : 3,
        "week" : 9
    },
    "YearlySpends" : [ 
        -63.3
    ],
    "totalYearlyAmount" : -63.3,
    "MonthlySpends" : [ 
        -63.3
    ],
    "totalMonthlyAmount" : -63.3,
    "WeeklySpends" : [ 
        -63.3
    ],
    "totalWeeklyAmount" : -63.3
}

/* 6 */
{
    "_id" : {
        "name" : "Amazon",
        "year" : 2017,
        "month" : 3,
        "week" : 12
    },
    "YearlySpends" : [ 
        -61.3
    ],
    "totalYearlyAmount" : -61.3,
    "MonthlySpends" : [ 
        -61.3
    ],
    "totalMonthlyAmount" : -61.3,
    "WeeklySpends" : [ 
        -61.3
    ],
    "totalWeeklyAmount" : -61.3
}

CẬP NHẬT

Nếu bạn muốn bao gồm các bộ lọc trong hoạt động tổng hợp thì tôi khuyên bạn nên sử dụng $ match truy vấn như là giai đoạn đường ống đầu tiên. Tuy nhiên, nếu có $ match bước sau đó các bước trước đó sẽ được thay đổi một chút vì bạn sẽ tổng hợp các kết quả đã lọc, rất khác với việc tổng hợp tất cả các tài liệu như ban đầu và sau đó áp dụng bộ lọc trên các kết quả.

Nếu bạn muốn sử dụng bộ lọc-trước-sau-tổng hợp định tuyến, hãy cân nhắc chạy một hoạt động tổng hợp sử dụng $ match là bước đầu tiên lọc tài liệu theo nhà cung cấp, sau đó đến $ redact bước đường dẫn để lọc thêm các tài liệu trên phần tháng của trường ngày và sau đó phần còn lại sẽ là $group giai đoạn:

Statements.aggregate([
    { "$match": { "name": req.params.vendor } },
    {
        "$redact": {
            "$cond": [
                { "$eq": [{ "$month": "$date" }, parseInt(req.params.month) ]},
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    .....
    /*
        add the remaining pipeline steps after
    */
], function(err, data){
    if (err) throw err;
    console.log(data);
})

Nếu bạn muốn sử dụng nhóm-trước-sau-lọc định tuyến, thì bộ lọc sẽ nằm sau đường ống cuối cùng cung cấp kết quả được nhóm lại nhưng được áp dụng trên các trường khác nhau vì các tài liệu ở phần đó của luồng sẽ khác với lược đồ ban đầu.

Lộ trình này không hoạt động vì bạn đang bắt đầu hoạt động tổng hợp với tất cả các tài liệu trong bộ sưu tập và sau đó lọc sau đó:

Statements.aggregate([
    .....
    /*
        place the initial pipeline steps from 
        the original query above here
    */
    .....
    { 
        "$match": { 
            "_id.name": req.params.vendor,
            "_id.month": parseInt(req.params.month)
        } 
    }
], function(err, data){
    if (err) throw err;
    console.log(data);
})

Đối với nhiều thông số bộ lọc ngày, $ redact toán tử sẽ là

{
    "$redact": {
        "$cond": [
            {
                "$and": [
                     { "$eq": [{ "$year": "$date" },  parseInt(req.params.year)  ]},
                     { "$eq": [{ "$month": "$date" }, parseInt(req.params.month) ]},
                     { "$eq": [{ "$week": "$date" },  parseInt(req.params.week)  ]}
                ]
            },
            "$$KEEP",
            "$$PRUNE"
        ]
    }
}



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Cách loại trừ giá trị null khỏi truy vấn điền Mongoose

  2. Làm cách nào để trả về một mảng các đối tượng mongodb trong pymongo (không có con trỏ)? MapReduce có thể làm điều này không?

  3. g ++ không thể liên kết tĩnh libmongcxx (r3.0.2) nhưng liên kết động hoạt động

  4. Các phương pháp hay nhất để bảo mật MongoDB

  5. Làm thế nào để xem những truy vấn nào đang sử dụng một chỉ mục trong MongoDB?