C#使用GroupBy查询MongoDB

时间:2017-07-12 19:24:06

标签: c# mongodb linq

我有一个mongodb对象如下:

public class Form
{
    public string FormId { get; set; } 
    public boolean Status { get; set; } //Published or Draft
    public int Version { get; set; } //The version of the same forms.
}

对于相同的FormId,可能有不同的版本号和不同的状态。一些示例数据,例如:

{
  "FormId":"1",
  "Status":true,
  "Version":1
};
{
  "FormId":"1",
  "Status":true,
  "Version":2
};
{
  "FormId":"2",
  "Status":true,
  "Version":1
};
{
  "FormId":"2",
  "Status":true,
  "Version":2
};
{
  "FormId":"2",
  "Status":false,
  "Version":1
}

现在我想获得一个表单列表,对于相同的FormId,Status为true且版本号最大。所以查询结果应该是:

{
  "FormId":"1",
  "Status":true,
  "Version":2
} 

{
  "FormId":"2",
  "Status":true,
  "Version":2
}

我尝试使用Lambda表达式在C#中编写查询:

this.AsQueryable<Form>().Where(p=>p.Status == true)
            .GroupBy(item=>item.FormId)
            .Select(t=>t.OrderByDescending(c => c.Version).FirstOrDefault()).ToList();

但我收到了错误:

  

其他信息:表达式树{document}中不支持System.Linq.Enumerable类型的FirstOrDefault .OrderByDescending(c =&gt; c.Version).FirstOrDefault()。

有谁知道我的代码出了什么问题?那么,如何知道表达式树支持或不支持的内容?

我发现,如果我按照以下方式编写查询,它会起作用,但我相信这不是一个好方法。

return this.AsQueryable<FormTemplateEntity>().Where(p=>p.Status == true).ToList()
            .GroupBy(item => item.FormId).ToList()
            .Select(t => t.OrderByDescending(c => c.Version).FirstOrDefault()).ToList();

3 个答案:

答案 0 :(得分:1)

更新了我的语法并进行了测试以便正常运行。

this.Where(x => x.Status)
            .GroupBy(item => new { item.FormId, item.Status })
            .Select(x =>
                new Form
                {
                    FormId = x.First().FormId,
                    Status = x.First().Status,
                    Version = x.OrderByDescending(c => c.Version).First().Version
                }
            ).ToList();

输出: [{&#34; FormId&#34;:&#34; 1&#34;&#34;状态&#34;:真,&#34;版本&#34;:2},{&#34; FormId&# 34;:&#34; 2&#34;&#34;状态&#34;:真,&#34;版本&#34;:2}]

用于测试的实际代码:

        var _json =
            "[{  \"FormId\":\"1\",  \"Status\":true,  \"Version\":1},{  \"FormId\":\"1\",  \"Status\":true,  \"Version\":2},{  \"FormId\":\"2\",  \"Status\":true,  \"Version\":1},{  \"FormId\":\"2\",  \"Status\":true,  \"Version\":2},{  \"FormId\":\"2\",  \"Status\":false,  \"Version\":1}]";
        var js = new JavaScriptSerializer();
        List<Form> resultList = js.Deserialize<List<Form>>(_json);
        var groupedResult = resultList.Where(x => x.Status).GroupBy(item => new { item.FormId, item.Status })
            .Select(x =>
                new Form
                {
                    FormId = x.First().FormId,
                    Status = x.First().Status,
                    Version = x.OrderByDescending(c => c.Version).First().Version
                }
            ).ToList();
        var output = js.Serialize(groupedResult);

答案 1 :(得分:0)

 public List<Form> GetFromDetails()
{
    var DB = new Database();
    var collection = DB.GetCollection<Form>();

    var query = new QueryBuilder<Form>();
    var queryLst = new List<IMongoQuery>();
    // {
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":1
    //};
    //{
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":2
    //};
    List<Form> finalResult = new List<Form>();


    finalResult = collection.FindAll().Where(x => x.Status == true).ToList(); // pasing id 1
    // {
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":1
    //};
    //{
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":2
    //};
    var finalResults = finalResult.Select(n => new Form
    {
        FormId = n.FormId,
        Status = n.Status,
        Version = finalResult.OrderByDescending(v => v.Version).First().Version
    });
    // {
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":2
    //};
    //{
    //  "FormId":"1",
    //  "Status":true,
    //  "Version":2
    //};
    DB.Dispose();
    return finalResult;
}

上面的方法将有所帮助,因为我自己做了一个演示工作

答案 2 :(得分:0)

它对我不起作用,但是我可以通过使用Group之前的Sort来实现。

return _context.Products
                .Aggregate() 
                .Sort(Builders<Product>.Sort.Descending("InsertedDate"))
                .Group(x => x.Code, g => new {Code = g.Key, LastInsertedDate =  g.First().InsertedDate })
                .ToList();