簡體   English   中英

日期之間的MongoDB C#驅動程序聚合返回空字段

[英]MongoDB C# driver aggregation between dates returns null fields

我正在使用mongodb的c#驅動程序,並希望對我正在創建的Web API使用聚合查詢。 對於我的聚合查詢,我關注的是具有用戶名,日期和步驟的配置文件類。 我想創建一個查詢,選擇用戶名並獲取給定周的總步數,按總步數降序排列。 我只想顯示他們的用戶名和他們的總步數。

當我嘗試聚合查詢時,我遇到了一些問題,我的某些字段將顯示為null。 所以,我認為我的查詢結構不正確。

我有一個“配置文件”類,我目前用於我的數據。

[BsonIgnoreExtraElements]
[DataContract]
public class Profile 
{   
    [DataMember]
    public string Username { get; set; }

    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public uint? Steps { get; set; }
}

我使用以下方法創建了一些測試數據,例如配置文件

//Test data
for (uint index = 1; index < 20; index++)
{      
    Profile aprofile = new Profile
    {   
        Username = string.Format("testuser{0}", index),
        Date = RandomDay(),
        Steps = (index + index + index)*2

    };
    AddProfile(aprofile);
}

如果我運行代碼幾次並查詢特定用戶,我得到的數據是這樣的:

[{"Username":"testuser1","Date":"2014-07-03T00:00:00Z","Steps":6},
{"Username":"testuser1","Date":"2014-07-07T05:00:00Z","Steps":6},
{"Username":"testuser1","Date":"2014-07-17T05:00:00Z","Steps":6},
{"Username":"testuser1","Date":"2014-07-18T05:00:00Z","Steps":6}]

然后,我有幾個靜態方法來查找我的聚合查詢的最早日期和最新日期。

//gets a datetime for the earlist date and time possible for the current week
public static DateTime GetStartOfCurrentWeek()
{
    int DaysToSubtract = (int)DateTime.Now.DayOfWeek;
    DateTime dt = DateTime.Now.Subtract(TimeSpan.FromDays(DaysToSubtract));
    return new DateTime(dt.Year, dt.Month, dt.Day, 0, 0, 0, 0);
}

//gets a datetime for the latest date and time possible for the current week
public static DateTime GetEndOfCurrentWeek()
{
    DateTime dt = GetStartOfCurrentWeek().AddDays(6);
    return new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59, 999);
}

我在聚合查詢中的嘗試如下。

//Here is my aggregation query to get all profiles within a given week, 
public IEnumerable<Profile> GetAllProfiles()
{
    DateTime StartofWeek = GetStartOfCurrentWeek();
    DateTime EndofWeek = GetEndOfCurrentWeek();


    var match = new BsonDocument 
                {{ "$match", new BsonDocument 
                     {{ "Date", new BsonDocument {
                            {"$gte", StartofWeek},
                            {"$lt", EndofWeek}
                      }}}
                }};

    var group = new BsonDocument
                {{"$group",
                    new BsonDocument
                    {{ "_id", new BsonDocument
                         {{"id", "$Username"},

                    }},
                         {"Steps",  new BsonDocument
                              {{"$sum", "$Steps"}}
                    }}
                }};


    var sort =  new BsonDocument
                {{"$sort", new BsonDocument
                    {{"Steps", -1}}

                }};    



    var pipeline = new[] {match, group, sort};      

    var args = new AggregateArgs { Pipeline = pipeline, OutputMode = AggregateOutputMode.Inline };

    // run the aggregation query and get a list of BsonDocuments
    IEnumerable<BsonDocument> documents = _profiles.Aggregate(args);
}

但是,我得到的結果是將用戶名顯示為Null,將日期顯示為null。

[{"Username":null,"Date":"0001-01-01T00:00:00","Steps":96},
{"Username":null,"Date":"0001-01-01T00:00:00","Steps":66},
{"Username":null,"Date":"0001-01-01T00:00:00","Steps":24}]

我需要做什么來獲取我的文檔數組,以便顯示用戶名以及我擁有的總步驟(似乎確實有效)。 我不想在查詢結果中使用日期。 只是用戶名及其周的總步數。

我真的不明白為什么你需要用BSon查詢你的mongo。 你有你的模型類。 您嘗試執行的聚合將如下所示:

var result = collection.Aggregate()
    .Match(r => r.Date >= StartofWeek && r.Date < EndofWeek)
    .Group(r=>r.Username, r=> new {UserName = r.Key, Dates  = r.Select(d=>d.Date),  Steps = r.Sum(x=>x.Steps)})
    .ToList();

請注意,您可能不會獲得一個日期,而是它的數組,因此我將其聚合為Dates

原因,為什么你沒有看到日期和用戶名是你不查詢它,在你的組聲明中,我只看到一些步驟。 如果你真的想繼續以這種方式查詢,你應該將它添加到你的小組階段,例如:

var group = new BsonDocument
             {
                    { "_id", new BsonDocument{{"id", "$Username"},
             }},
             {"Steps",  new BsonDocument{{"$sum", "$Steps"}}},
             { "Dates", new BsonDocument{{"$addToSet", "$Date"}} },
             { "Username", new BsonDocument{{"$first", "$Username"}} },
        };

這樣我可以在生成的BsonDocument中看到用戶名和日期。

但正如我已經說過的,這種查詢Mongo的方式並不是c#中最好的方法。

您的group賽階段有一個缺陷,那就是您沒有在查詢中包含您想要的字段。

只需更改group賽階段,您就應該獲得所需的字段。

var group = new BsonDocument
    {{"$group",
        new BsonDocument
        {
            { "_id", new BsonDocument
                {{"id", "$Username"}}
            },
            { "Steps",  new BsonDocument
                {{"$sum", "$Steps"}}
            },
            { "Username", new BsonDocument
                {{"$first", "$Username"}} // since the rest of the selected object is groupped, we should give a strategy to pick a $Username, and it is safe to use $first aggregate function here
            }
        }
    }};

如果您對輸出結果中的日期不滿意,只需添加project階段,然后重新整理輸出文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM