如何查找在时间范围内发生的事件(mongo)

时间:2015-08-11 11:20:00

标签: mongodb aggregation-framework

我有以下文档结构:

{ _id:ID1
  value: { data:{userData:{name:aaa,surname:bbb}}
           events:[
                    {even1tName:{timestamp:UNIX_TIMESTAMP,value:NUMBER}},
                    {even2tName:{timestamp:UNIX_TIMESTAMP,value:NUMBER}},
                    {even3tName:{timestamp:UNIX_TIMESTAMP,value:NUMBER}},
                    {even4tName:{timestamp:UNIX_TIMESTAMP,value:NUMBER}},
                  ],
            activity:{countEvents:INTEGER,totalValue:NUMBER}
           }
}

这是MapReduce管道的输出,我需要在一个时间范围内找到使用聚合,用户有一定数量的事件和一定数量的值(总结)。考虑一下这些是在线买家,我需要找到那些在过去一个月内进行了3次购买的商品或那些购买总金额超过300美元的商品。

1 个答案:

答案 0 :(得分:1)

你的问题对信息有点关注,但主要的是,只要有一致的" keyname"在文档中命名然后这确实不是问题:

  db.junk.aggregate([
    // Match where type within timeframe
    { "$match": {
      "value.events.confirmedSale.timestamp": {
        "$gte": startTime, "$lt": endTime
      }
    }},

    // Pre-filter the array for required data
    { "$project": {
      "value": {
        "data": "$value.data",
        "events": {
          "$setDifference": [
            {"$map": {
              "input": "$value.events",
              "as": "el",
              "in": {
                "$cond": [
                  { "$and": [
                    { "$gte": [ "$$el.confirmedSale.timestamp", startTime ] },
                    { "$lt": [ "$$el.confirmedSale.timestamp", endTime ] }
                  ]},
                  "$$el",
                  false
                ]
              }
            }},
            [false]
          ]
        }
      }
    }},

    // Unwind array elements for processing
    { "$unwind": "$value.events" },

    // Group data
    { "$group": {
      "_id": "$_id",
      "value": { "$sum": "$value.events.confirmedSale.value"},
      "count": { "$sum": 1 }
    }},
    // Filter results on totals
    { "$match": {
        "value": { "$gte": 300, "count": { "$gte": 3 } }
    }}
  ])

但是,由于文档结构的原因,您无法真正获得更广泛的内容。这样的命名需要"路径名称"嵌入对象是绝对的,这种特殊情况对索引也不好。

通过对文档创建的一些控制,它应该看起来更像这样:

{ _id: 1,
  value: { 
    data:{
      userData:{name:"aaa",surname:"bbb"}
    },
    events:[
      { "type": "adCLick",  "timestamp": 1234, "value": 1234 },
      { "type": "confirmedSale", "timestamp": 5678, "value": 5678 },
      { "type": "confirmedSale", "timestamp": 4567, "value": 4567 },
      { "type": "something",  "timestamp": 9876, "value": 9876}
    ]
  }
}

现在你在这里使用的字段名称实际上只是一个一致的"数据"属性,查询可以更清晰地读取,使用您无法执行的组合事件执行更多操作,并且还可以使用索引来提高性能。

MongoDB主要是一个"数据库",如果你没有保持一致的命名路径,那么你将会有性能和功能损失。聚合框架是"高性能"使用JavaScript在mapReduce上选项。对于聚合框架,使用set key模式是合适的,但是如果你改变了那个模式,那么你唯一的选择就是mapReduce。