2015-10-14 83 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; } 
} 

我希望這將是有益的。謝謝! :)