"Group By"基于文档的存储中的实体?



如果这是重复的,我很抱歉;我已经完成了我的搜索份额,但我已经弄清楚要搜索什么。

假设您有一个学生数据库,并且您想根据性别平均他们的分数。使用标准问题关系数据库,这是非常微不足道的。它可能需要具有显式联接的查询,或者您可能只使用导航属性或其他内容,但它看起来有点像这样:

var averageScore = db.Grades
    .Where(grade => grade.Student.Gender == selectedGender)
    .Average();

但是,如果您连接到基于文档的系统,而您的数据结构只是一个嵌入了 Grade 对象集合的学生对象,该怎么办?

var averageScore = db.Students.GroupBy(student => student.Gender)
    .ThisDoesNotWork(no => matter.What);

我已经尝试了三十种不同的方法来做一个 GroupBy,它设法将值集合转换为共享公共键的单个值集合,但没有一个奏效。我的大部分尝试都涉及在GroupBy中尝试SelectMany,并且 - 如果可能的话 - 让我们说编译器不喜欢我的床边方式。

编辑:不确定"格式"是什么意思。我们正在谈论的数据结构只是一个类,其中集合作为其成员之一。

class Student
{
    public string Name { get; set; }
    public Gender Gender { get; set; }
    public ICollection<int> Grades { get; set; }
}

SelectMany 将为您展平集合。

var average = db.Students
    .Where(s => s.Gender == selectedGender)
    .SelectMany(s => s.Grades)
    .Average();

另一方面,GroupBy 会将特定元素组合在一起。 因此,如果您想按性别分组:

var averages = db.Students
    .GroupBy(
        s => s.Gender,
        (gender, group) => group
            .SelectMany(s => s.Grades)
            .Average());

"组"是一个 IEnumerable,即适合每个组的所有学生。

Rich 的

回答让我对SelectMany()有了更深入的思考(加上我下班了,很无聊(,所以我投入了更多的工作,这就是我得到的:

var averagesByGender = db.Students
    .SelectMany(
        student => student.Grades,
        (student, grade) => new { Gender = student.Gender, Grade = grade })
    .GroupBy(
        record => record.Gender,
        record => record.Grade)
    .Select(group => new { group.Key, Average = group.Average() });

SelectMany()的工作方式与任何SQL数据库中的join语句几乎完全相同:每个年级都有一条记录,其中包含相关的学生信息,然后您可以从那里以老式的方式查询任何您想要的内容(或者,如我的示例,您可以为每个代表的性别获得一个结果(。

唯一的皱纹是,显然,这太关系化了......就像在RavenDB中一样,拒绝尝试将其转换为查询。幸运的是,如果你把它藏在后面,那.ToList()就无关紧要了。想知道它是否会以与MongoDB相同的方式工作。

最新更新