【问题标题】:mongodb aggregation of multiple valuesmongodb聚合多个值
【发布时间】:2017-06-28 11:29:31
【问题描述】:

我正在尝试使用 mongodb 进行分析,但我对它很陌生,虽然我让它适用于 1 个查询,但我认为它的效率不高,这是我的数据集示例

{
_id: ObjectId("54442882fa2e117a55f3458b"),
analytic_num: 185,
createdAt: ISODate("2014-10-19T21:09:22.167Z"),
updatedAt: ISODate("2014-10-19T21:09:22.167Z"),
rawBrowser: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:33.0) Gecko/20100101 Firefox/33.0",
gender: "male",
eventId: "accepted",
type: "member",
relationshipStatus: "Single",
ageRange: "18-25",
uid: "53f79ae6f158168161f04d27",
cid: "54370fa7498a776e1c065120",
education: ["high_school", "professional_degree"],
interestedIn: ["female"],
__v: 0
}

这是我正在尝试的查询

db.analytics.aggregate([{
$match: {
    createdAt: {
        $gte: new Date(2014, 9, 15),
        $lt: new Date(2014, 9, 28)
    }
}
}, {
$project: {
    _id: 0,
    minute: {
        $minute: "$createdAt"
    },
    hour: {
        $hour: "$createdAt"
    }
}
}, {
$group: {
    _id: {
        minute: "$minute",
        hour: "$hour"
    },
    hits: {
        $sum: 1
    }
}
}]);

这是我得到的结果

{ "_id" : { "minute" : 33, "hour" : 21 }, "hits" : 1 }
{ "_id" : { "minute" : 29, "hour" : 21 }, "hits" : 6 }
{ "_id" : { "minute" : 6, "hour" : 22 }, "hits" : 2 }
{ "_id" : { "minute" : 9, "hour" : 21 }, "hits" : 1 }

一切都很好,但我每小时的每一分钟都得到点击,如果我只想点击,那很好

但如果我需要按类型、性别或年龄范围查找命中,我需要更改 $match 查询,通过更改 $matvh 对所有属性运行此查询效率不高

如何在一个查询中获取类型、性别、angRange 的所有匹配项 我想要这样的结果

{ "_id" : { "minute" : 33, "hour" : 21 }, "hits" : 30, "member" :2 "single": 12 ,"male" :12 }
{ "_id" : { "minute" : 34, "hour" : 21 }, "hits" : 50, "member" :22 "single": 12 ,"male" :12 }

请帮忙

谢谢

【问题讨论】:

  • 我认为聚合不能在一个查询中得到结果。例如字段gender的值可以是男也可以是女;分别求和,您必须通过将每个指定为组 id 的一部分来对它们进行分组。因此,您最后必须将这些字段一一分组。使用mapReduce应该可以通过one query得到结果。
  • @Wizard 你完全不正确。我想建议您暂时不要在这里尝试回答人们,并花一些时间观察和学习。太多的误导性陈述来自您对该主题的缺乏了解。这对人们没有帮助。

标签: javascript node.js mongodb mongodb-query aggregation-framework


【解决方案1】:

您正在寻找$cond 运算符。这使您可以评估条件,然后决定是否将 true|false 返回到您要返回的值。在这种情况下,您是否想为 $sum 操作添加增量或不:

db.analytics.aggregate([
    { "$match": {
        "createdAt": {
            "$gte": new Date(2014, 9, 15),
            "$lt": new Date(2014, 9, 28)
        }
    }}, 
    { "$group": {
        "_id": {
            "minute": { "$minute": "$createdAt" },
            "hour": { "$hour": "$createdAt" }
        },
        "hits": { "$sum": 1 },
        "member": {
            "$sum": {
                "$cond": [
                    { "$eq": [ "$type", "member" ] },
                    1,
                    0
                ]
            }
        },
        "single": {
            "$sum": {
                "$cond": [
                    { "$eq": [ "$relationshipStatus", "single" ] },
                    1,
                    0
                ]
            }
        },
        "male": {
            "$sum": {
                "$cond": [
                    { "$eq": [ "$gender", "male" ] },
                    1,
                    0
                ]
            }
        }
    }}
]);

所以$cond 运算符基本上是一个“三元”或if..then..else 构造,它评估一个条件并根据该条件的确定方式返回一个值true|false。您以这种方式使用它来确定返回的值。

小心使用日期聚合运算符。也许您在这里想要的是每小时的每一分钟,在该范围内的所有日子里汇总。但通常人们只想要每天的离散时间段,甚至按分钟。

小心你的要求,你可能会得到它。

【讨论】:

  • 嘿@Neil 我得到 SyntaxError: Unexpected number 你能弄清楚它在哪里
  • 我知道 $cond 中缺少分号
  • 嘿@Neil 我正在评估您的答案,这似乎正是我想要的,我只想问一件事是否我有一个数组,例如教育:[“high_school”,“professional_degree”],如何选择像 high_school ,professional_degree 这样的个人命中,因为我不能使用 $eq 运算符可能是我应该使用 $in 运算符但我得到错误“异常:无效运算符'$in'”,如果我不能使用数组你有任何其他建议我如何解决这个问题,谢谢
猜你喜欢
  • 2018-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 2017-10-08
  • 2013-07-16
  • 2021-07-25
相关资源
最近更新 更多