MongoDB聚合查询按日期分组

5

我在mongoDB中有以下这个集合

{ _id, startTime, duration }

基本思路是摄像头监测人群,一旦检测到人,就保存开始时间(startTime),一旦人消失,就保存持续时间(duration)。因此,实体基本上会说“一个人在X时间出现,并且在镜头范围内持续了Y毫秒”。startTime和duration都是数字值。
因此,我想执行各种查询,例如: 1. 每月/每年的人数 2. 每月持续时间 > 5000ms 的人数
等等。
虽然我对MongoDB还比较陌生,但我在聚合框架方面遇到了一些麻烦,所以如果有人能给我一个如何进行上述查询的想法,我会很感激的,这将为我提供一些起点。
编辑: 好的,我已经尝试过几次,但没有成功。现在我的对象具有以下形式:
{
  "_id" : ObjectId("52de407c75895eaf5ea99715"),
  "startTime" : "new Date('02 01 2011 08:36:54')",
  "duration" : 27000
}

我正在尝试这个查询:

 db.collection.aggregate(
        {$project : {
             year : {$year : "$startTime"}

        }},
        {$group : {
             _id : {year : "$year"}, 
             count : {$sum : 1}
        }}
    )

但是我遇到了以下异常:
Error occurred in performing aggregation
Command 'aggregate' failed: exception: can't convert from BSON type String to Date (response: { "errmsg" : "exception: can't convert from BSON type String to Date", "code" : 16006, "ok" : 0.0 })
Type: MongoDB.Driver.MongoCommandException
Stack:    at MongoDB.Driver.Operations.CommandOperation`1.Execute(MongoConnection connection)
   at MongoDB.Driver.MongoCollection.RunCommandAs[TCommandResult](IMongoCommand command, IBsonSerializer resultSerializer, IBsonSerializationOptions resultSerializationOptions)
   at MongoDB.Driver.MongoCollection.RunCommandAs[TCommandResult](IMongoCommand command)
   at MongoDB.Driver.MongoCollection.Aggregate(IEnumerable`1 operations)
   at MangoUI.ComAggregate.kRemove_Click(Object sender, EventArgs e)
Inputs:: 
Command:  aggregate
Ok:       False
ErrorMsg: exception: can't convert from BSON type String to Date
Request:  { "aggregate" : "person", "pipeline" : [{ "$project" : { "year" : { "$year" : "$startTime" } } }, { "$group" : { "_id" : { "year" : "$year" }, "count" : { "$sum" : 1 } } }] }
Response: { "errmsg" : "exception: can't convert from BSON type String to Date", "code" : 16006, "ok" : 0.0 }

你可以查看这个 MongoDB 分组文档:http://docs.mongodb.org/manual/reference/method/db.collection.group/ - Raj Subit
如果您想执行这些类型的查询,应将文档中的 startTime 更改为 Date 类型,而不是数字。 - JohnnyHK
2个回答

15
你可以使用聚合框架完成它们。
给我每个月/年的人数。
db.collection.aggregate(
    {$project : {
         year : {$year : "$startTime"}, 
         month : {$month : "$startTime"}
    }},
    {$group : {
         _id : {year : "$year", month : "$month"}, 
         count : {$sum : 1}
    }}
)

给我每个月持续时间大于5000毫秒的人数

db.collection.aggregate(
    {$project : {
         year : {$year : "$startTime"}, 
         month : {$month : "$startTime"}, 
         duration: {$cond: [{$gt: ['$duration', 5000]}, 1, 0]}
    }},
    {$group : {
         _id : {year : "$year",month : "$month"}, 
         duration : {$sum : "$duration"}
    }}
)

了解更多信息,请查看聚合框架


我尝试了第一个,但似乎出现了以下异常:命令“aggregate”失败:异常:无法将BSON类型NumberLong64转换为Date(响应:{"errmsg":"exception: can't convert from BSON type NumberLong64 to Date","code":16006,"ok":0.0})。 - ChrisGeo
我忘了提到。为了使用$year和$month运算符,startTime应该是一个日期格式。它不能与Long一起使用。 - Parvin Gasimzade
据我所知,没有办法在运行时将长整型转换为日期。 - Parvin Gasimzade
好的,我已经将日期数据更改为字符串形式:"Jan 2, 2011 9:50:48 AM"。我可以使用它吗?然而,我似乎仍然在上面的代码中遇到错误。 - ChrisGeo
1
你不知道这有多帮助我了。+1 - Hunter
显示剩余3条评论

1
请参考MongoDB兼容的数据格式http://docs.mongodb.org/manual/reference/bson-types/#document-bson-type-date
以下是测试聚合的方法。
 rs1:PRIMARY> 
rs1:PRIMARY> db.dbversitycol.insert({ "_id" : "1", "LastUpdatedOn" : new Date() , "company" : "microsoft" })
rs1:PRIMARY> db.dbversitycol.insert({ "_id" : "2", "LastUpdatedOn" : new Date() , "company" : "google" })
rs1:PRIMARY> db.dbversitycol.insert({ "_id" : "3", "LastUpdatedOn" : new Date() , "company" : "ibm" })
rs1:PRIMARY> db.dbversitycol.insert({ "_id" : "4", "LastUpdatedOn" : new Date() , "company" : "cisco" })
rs1:PRIMARY> db.dbversitycol.insert({ "_id" : "5", "LastUpdatedOn" : new Date() , "company" : "dbversity.com" })
rs1:PRIMARY> 
rs1:PRIMARY> db.dbversitycol.find()
{ "_id" : "1", "LastUpdatedOn" : ISODate("2014-11-28T13:09:13.203Z"), "company" : "microsoft" }
{ "_id" : "2", "LastUpdatedOn" : ISODate("2014-11-28T13:09:13.207Z"), "company" : "google" }
{ "_id" : "3", "LastUpdatedOn" : ISODate("2014-11-28T13:09:13.210Z"), "company" : "ibm" }
{ "_id" : "4", "LastUpdatedOn" : ISODate("2014-11-28T13:09:13.213Z"), "company" : "cisco" }
{ "_id" : "5", "LastUpdatedOn" : ISODate("2014-11-28T13:09:14.035Z"), "company" : "dbversity.com" }
rs1:PRIMARY> 
rs1:PRIMARY> 
rs1:PRIMARY> db.dbversitycol.aggregate(
... {
...     "$project" :
...     {
...        _id : 0,
...        "datePartDay" : {"$concat" : [
...            {"$substr" : [{"$dayOfMonth" : "$LastUpdatedOn"}, 0, 2]}, "-",
...            {"$substr" : [{"$month" : "$LastUpdatedOn"}, 0, 2]}, "-",
...            {"$substr" : [{"$year" : "$LastUpdatedOn"}, 0, 4]}
...       ] }
...     }
... },
... { "$group" :
...     { "_id" : "$datePartDay", "Count" : { "$sum" : 1 } }
...     }
... )
{ "result" : [ { "_id" : "28-11-2014", "Count" : 5 } ], "ok" : 1 }
rs1:PRIMARY> 
rs1:PRIMARY> 



rs1:PRIMARY> db.dbversitycol.aggregate(
...     {$project : {
...          year : {$year : "$LastUpdatedOn"}, 
...          month : {$month : "$LastUpdatedOn"}
...     }},
...     {$group : {
...          _id : {year : "$year", month : "$month"}, 
...          count : {$sum : 1}
...     }}
... )
{
        "result" : [
                {
                        "_id" : {
                                "year" : 2014,
                                "month" : 11
                        },
                        "count" : 5
                }
        ],
        "ok" : 1
}
rs1:PRIMARY>

您可以在http://www.dbversity.com/查看更多相关文章。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接