c#和mongodb:使用过滤器聚合

时间:2017-08-23 10:01:40

标签: c# mongodb linq aggregate

我正在使用最新版本的mongodb和MongoDB驱动程序用于C#。我创建了一个小例子,它可以解释我的问题。我的目标是使用过滤器创建一些条件Count(),条件First()或Average()。它都不起作用。

这个问题的最佳解决方案是什么。谢谢你的提示

    class MealDocument
    {
        public string name { get; set; }
        public DateTime time { get; set; }
        public Type type { get; set; }
        public double calorie { get; set; }
        public enum Type { breakfast, launch, dinner }
    }

    class MealAnalysis
    {
        public string name { get; set; }
        public int numberOfBreakfast { get; set; }
        public DateTime firstLaunch { get; set; }
        public double averageDinnerCalorie { get; set; }
    }

    public void Test()
    {
        var collection = Database.GetCollection<MealDocument>("meal_test");

        collection.InsertMany(new MealDocument[] {
            new MealDocument { name = "Thomas", type = MealDocument.Type.breakfast, calorie = 100, time = new DateTime(2017,8,1) },
            new MealDocument { name = "Thomas", type = MealDocument.Type.breakfast, calorie = 100, time = new DateTime(2017,8,2) },
            new MealDocument { name = "Thomas", type = MealDocument.Type.launch, calorie = 800, time = new DateTime(2017,8,3) },
            new MealDocument { name = "Thomas", type = MealDocument.Type.dinner, calorie = 2000, time = new DateTime(2017,8,4) },
            new MealDocument { name = "Peter", type = MealDocument.Type.breakfast, calorie = 100, time = new DateTime(2017,8,5) },
            new MealDocument { name = "Peter", type = MealDocument.Type.launch, calorie = 500, time = new DateTime(2017,8,6) },
            new MealDocument { name = "Peter", type = MealDocument.Type.dinner, calorie = 800, time = new DateTime(2017,8,7) },
            new MealDocument { name = "Paul", type = MealDocument.Type.breakfast, calorie = 200, time = new DateTime(2017,8,8) },
            new MealDocument { name = "Paul", type = MealDocument.Type.launch, calorie = 600, time = new DateTime(2017,8,9) },
            new MealDocument { name = "Paul", type = MealDocument.Type.launch, calorie = 700, time = new DateTime(2017,8,10) },
            new MealDocument { name = "Paul", type = MealDocument.Type.dinner, calorie = 1200, time = new DateTime(2017,8,11) }
        });

        var analysis = collection.Aggregate()
            .Group(
                doc => doc.name,
                group => new MealAnalysis
                {
                    name = group.Key,

                    // !!!! The condition in the Count() gets ignored
                    numberOfBreakfast = group.Count(m => m.type == MealDocument.Type.breakfast),

                    // !!!! Exception --> Not supported
                    averageDinnerCalorie = group.Where(m => m.type == MealDocument.Type.dinner).Average(m => m.calorie),

                    // !!!! Exception --> Not supported
                    firstLaunch = group.First(m => m.type == MealDocument.Type.launch).time
                }
            );

        var query = analysis.ToString();

        var result = analysis.ToList();
    }

1 个答案:

答案 0 :(得分:0)

我花了几个小时,我不能让司机在你需要的时候工作。虽然我没有提出正确的解决方案,但这是我得到的最接近的。我不是这个解决方案的忠实粉丝,因为它计算了很多你不需要的东西,但如果Db不那么大,它可能会运行得很好,直到找到解决问题的方法。

var groupRes = collection.Aggregate()
                .Group
                    (
                        x => new { x.name, x.type },
                        g => new
                        {
                            key = g.Key,
                            count = g.Count(),
                            averageCalorie = g.Average(y => y.calorie),
                            first = g.First().time
                        }
                    )
                .ToList();
            var paulStat = new MealAnalysis()
            {
                name = "Paul",
                averageDinnerCalorie = groupRes.FirstOrDefault(x => (x.key.name == "Paul" && x.key.type == Type.dinner)).averageCalorie,
                numberOfBreakfast = groupRes.FirstOrDefault(x => (x.key.name == "Paul" && x.key.type == Type.breakfast)).count,
                firstLaunch = groupRes.FirstOrDefault(x => (x.key.name == "Paul" && x.key.type == Type.launch)).first
            };

你可以看到我为每个枚举计算你需要的东西,然后为每个人构建他的MealAnalysis。也许有人找到你需要的解决方案。

祝你好运!