2015-10-14 131 views
3

我正在写一个功能,我需要按日期进行分组。以下是我目前的工作方式:在Mongodb中按日期汇总

//Assuming this is my sample document in the collection 
{ 
    "_id" : ObjectId("56053d816518fd1b48e062f7"), 
    "memberid" : "7992bc31-c3c5-49e5-bc40-0a5ba41af0bd", 
    "sourceid" : NumberInt(3888), 
    "ispremium" : false, 
    "createddate" : { 
     "DateTime" : ISODate("2015-09-25T12:26:41.157+0000"), 
     "Ticks" : NumberLong(635787808011571008) 
    }, 
    "details": { 
     //a large sub-document 
    } 
} 

鉴于会员ID,开始日期和结束日期;我需要搜索匹配这些过滤器的集合并按日期对结果进行分组。换句话说,我需要获得的结果是一个列表(例如,2015年10月12日 - 计数为5,13/10/2015 - 计数为2)。 StartDate和EndDate是DateTime的类型。

C#为编程语言我使用,目前,我写的方法是:

var builder = Builders<MyCollection>.Filter; 
    var filter = builder.Eq(d => d.MemberId, memberId) & builder.Gte(d => d.CreatedDate, startDate) & builder.Lt(d => d.CreatedDate, endDate.AddDays(1)); 

    var group = collection.Aggregate() 
          .Match(filter) 
          .Group(new BsonDocument { { "_id", "$createddate" }, { "count", new BsonDocument("$sum", 1) } }) 
          .ToListAsync().Result; 

我再反序列化的结果自定义类...

List<CustomAggregateResult> grouped = group.Select(g => BsonSerializer.Deserialize<CustomAggregateResult>(g)).OrderBy(g => g.Date).ToList(); 

如果该代码失败,这是显而易见的,是分组的一部分。对我来说最理想的是按日期而不是日期时间进行分组。我已阅读group documentation和一些类似的线程,但不幸的是,我无法得到它的工作。我的一个尝试是按照文档中的建议进行操作。对于原始蒙戈查询是:

db.mycollection.aggregate(
[ 
    { 
    $group : { 
     _id : { month: { $month: "$createddate" }, day: { $dayOfMonth: "$createddate" }, year: { $year: "$createddate" } }, 
    count: { $sum: 1 } 
    } 
    } 

] )

我已经离开了$比赛只是为了得到该位工作。我得到的例外是“不能从BSON类型的对象转换为日期”。

总之,我当前的代码基于DateTime(而不是日期)工作,但是“组”,并且它在一个特定日期结束了单独的计数。我很好奇它是否可以实现。未知是mongo的一部分,因为我还没有想出如何做到这一点(甚至在原始的mongo查询中)。

只是一些附加信息来澄清,我有在C#中的DateTime对象(不知道这是否会影响)以下数据注释:

[BsonDateTimeOptions(Representation = BsonType.Document)] 
public DateTime CreatedDate {get; set; } 

一个在我脑海中的解决方案是,是否有可能投影“createddate”字段,并将其格式化为“Ymd”,并根据投影字段进行分组。

我试着添加尽可能多的细节,以及迄今为止所做的工作,只是为了使它更清晰。我希望这不会造成任何混乱。我会很感激任何帮助/建议,这将有助于我产生我想要的结果。谢谢!

+0

从您的问题一开始的模式,似乎'createddate'是一个对象,并且实际的日期字段被嵌入,为什么你不尝试访问使用点符号的字段,即你的组表达式应该'_id:{month:{$ month:“$ createddate.DateTime”},day:{$ dayOfMonth:“$ createddate.DateTime”},year:{$ year:“$ createddate.DateTime”}}'? – chridam

+1

哇!一个微小的细节可以改变整个事情。感谢mil,@chridam。我可以修复它。 :) – Yavarino

回答

2

根据@chridam的评论,我能够修复它。再次感谢!

我写下面的解决方案,以防万一,如果有人遇到同样的问题,我做了。

我改变了我的查询,使我变成了:

var group = collection.Aggregate() 
         .Match(filter) 
         .Group(new BsonDocument { { "_id", new BsonDocument { { "month", new BsonDocument("$month", "$createddate.DateTime") }, { "day", new BsonDocument("$dayOfMonth", "$createddate.DateTime") }, { "year", new BsonDocument("$year", "$createddate.DateTime") } } }, { "count", new BsonDocument("$sum", 1) } }) 
         .ToListAsync().Result; 

这给了我一个序列化对象。然后,我反序列化入自定义类我:

var grouped = group.Select(g => BsonSerializer.Deserialize<RootObject>(g)); 

这是自定义类的定义,这将是一个有点抛光机:

public class Id 
{ 
    public int month { get; set; } 
    public int day { get; set; } 
    public int year { get; set; } 
} 

public class RootObject 
{ 
    public Id _id { get; set; } 
    public int count { get; set; } 
} 

我希望这将是有益的。谢谢! :)