Mongo - 第二个文件的平均值

时间:2014-10-17 09:24:48

标签: mongodb mongodb-query aggregation-framework

我正在尝试计算客户第二笔订单的平均订单金额。

我使用以下方法成功完成了第一个订单的平均金额:

db.users.aggregate([
{$match: {
    $and: [
        {$nor : [ { "emails.0.address" : "X@X.com" }, { "X.0.X" : "X@X.com" },{ "emails.0.address" : "X@X.com" },{ "emails.0.address" : "X@X.fr" } ]},
        {orders: {$exists: true}}
    ]
}},
{$unwind: "$orders"},
{$group: {
    _id: "$_id",
    firstOrder: {$first: "$orders"}
}},
{$group: {
    _id: "$_id",
    total: {$sum: "$firstOrder.total"}
}},
{$group: {
    _id: '',
    average: {$avg: "$total"}
}}

])

但是计算二阶的平均数量似乎有点不同。

我尝试使用$Slice,但它不适用于aggregate$Skip只跳过列表的第一个订单,而不是每个用户的第一个订单。

你对此有任何想法吗?

非常感谢你的帮助。 理查德

1 个答案:

答案 0 :(得分:0)

正如您基本上已经解决的那样,没有一种简单的方法可以获得数组的nth位置。但是你在正确的轨道上,只需要更多的处理和额外的调整。由于您不希望在没有二阶订单的情况下处理订单:

db.users.aggregate([

    // Match to make sure there is a second element, $and is actually implicit
    { "$match": {
        "$nor" : [ 
            { "emails.0.address" : "X@X.com" }, 
            { "X.0.X" : "X@X.com" },
            { "emails.0.address" : "X@X.com" },
            { "emails.0.address" : "X@X.fr" } 
        ],
        "orders.1": { "$exists": true }
    }},

    // Then unwind to de-normalize
    { "$unwind": "$orders"},

    // Keep the first order, and all the rest
    { "$group": {
        "_id": "$_id",
        "firstOrder": { "$first": "$orders" }
        "orders": { "$push": "$orders" }
    }},

    // Yep, unwind again
    { "$unwind": "$orders"},

    // Test to see the element that was already seen
    { "$project": {
        "orders": 1,
        "matched": { "$eq": [ "$orders", "$firstOrder" ] }
    }},

    // Filter out the matched element
    { "$match": { "matched": false } },

    // Now the $first element is actually the "second"
    { "$group": {
        "_id": "$_id",
        "secondOrder": { "$first": "$orders" }
    }},

    // Summing is redundant, just average over all of it
    { "$group": {
        "_id": null,
        "average": { "$avg": "$secondOrder.total" }
    }}
])

因此,通过有效地删除"第一个"来清除一些东西并获得第二个元素的平均值。结束操作中数组的元素。

如果你错过了早期行的含义:

        "orders.1": { "$exists": true }

基本上是一个小点符号"确保数组的第二个元素确实存在的技巧。有办法考虑"第一"数组的元素,当实际上没有第二个元素,但这可能是另一个问题,如果你在这里找不到答案。我知道我之前已经给出了处理不同数组长度的方法。