条件聚合器的MongoDb.Linq等效查询

时间:2019-05-28 16:21:58

标签: c# mongodb linq aggregation-framework mongodb-.net-driver

我通过以下方式将数据与MongoDb.Linq分组:

group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = from v0 in g2
                 where v0.VolId != g2.Key.SupId
                 select new { v0.VolFullName, v0.VolPeopleCount }
}

也就是说,我只想在Volunteers中使用Id与组密钥不同的密钥。我期望驱动程序生成一个条件$push,但是却给出了一个普通的条件:

"$push" : { 
    "VolFullName" : "$VolFullName", 
    "VolPeopleCount" : "$VolPeopleCount" 
}

现在,通过阅读此post,我能够将上述查询转换为以下查询:

"$push": {
    "$cond": [
        { "$ne": [ "$VolId", "$SupId" ] },
        { 
            "VolFullName": "$VolFullName",
            "VolPeopleCount": "$VolPeopleCount"
        },
        null
     ]
 }

这给了我想要的结果。我想知道如何指示csharp驱动程序生成上述查询。预先感谢!

编辑:根据@mickl的建议,我能够生成条件$push(以及条件$sum),但结果与预期的不同。假设我的收藏夹中包含以下文档:

{ N: "P_1", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_2", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_3", S: { I: "S_1", FN: "S_1" }, C: { I: "S_1", FN: "S_1" } }
{ N: "P_4", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_5", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_6", S: { I: "S_1", FN: "S_1" }, C: { I: "C_2", FN: "C_2" } }
{ N: "P_7", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_8", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }
{ N: "P_9", S: { I: "S_1", FN: "S_1" }, C: { I: "C_3", FN: "C_3" } }

此处NIFNSC分别表示名称,ID,全名,主管和创建者。因此,您可以看到主管S_1正在监督每个文档,已经创建了3个文档,另外2个创建者创建了6个文档,这些创建者也受到S_1的监督。我要做的是由主管然后由创建者汇总这些文档,并汇总创建的文档(人员)数量。因此,我的LINQ查询如下:

var q = from p in col.AsQueryable()
        group p by new
        {
           SupFullName = p.S.FN,
           SupId = p.S.I,
           CtorFullName = p.C.FN,
           CtorId = p.C.I
        } into g1
        select new
        {
            g1.Key.SupFullName,
            g1.Key.SupId,
            VolFullName = g1.Key.CtorFullName,
            VolId = g1.Key.CtorId,
            VolPeopleCount = g1.LongCount()
        } into r1
        group r1 by new { r1.SupId, r1.SupFullName } into g2
        select new
        {
           g2.Key.SupFullName,
           g2.Key.SupId,
           Volunteers = g2.Select(v => v.VolId != g2.Key.SupId
                           ? new { v.VolId, v.VolFullName, v.VolPeopleCount }
                           : null),
          SupPeopleCount = g2.Select(v => v.VolId == g2.Key.SupId 
                               ? v.VolPeopleCount 
                               : 0).Sum()
        } into r2
        orderby r2.SupPeopleCount descending
        select r2;

查询给我的输出是:

Supervisor: S_1, PeopleCount: 0
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3
   Creator: S_1, PeopleCount: 3

这不是我想要的。正确的输出将是

Supervisor: S_1, PeopleCount: 3
   Creator: C_3, PeopleCount: 3
   Creator: C_2, PeopleCount: 3

它通过以下方式生成条件聚合器(如果我在条件中删除前缀$_id,而仅保留$SupId,它就像一个超级按钮一样工作):

"__agg0": {
      "$push": {
         "$cond": [
             { "$ne": [ "$VolId", "$_id.SupId" ] },
             {
                "VolId": "$VolId",
                "VolFullName": "$VolFullName",
                "VolPeopleCount": "$VolPeopleCount"
             },
             null
         ]
      }
},
"__agg1": {
    "$sum": {
       "$cond": [
           { "$eq": [ "$VolId", "$_id.SupId" ] },
           "$VolPeopleCount",
           NumberLong(0)
       ]
   }
}

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以在LINQ语句中运行Select并使用三元运算符:

group r1 by new { r1.SupId, r1.SupFullName } into g2
select new
{
    g2.Key.SupFullName,
    Volunteers = g2.Select(x => x.VolId != x.SupId ? new { x.VolFullName, x.VolPeopleCount }: null)  
};

这被转换为以下聚合管道:

{ 
    "$group" : { 
        "_id" : { "SupId" : "$SupId", "SupFullName" : "$SupFullName" }, 
        "__agg0" : { 
            "$push" : { 
                "$cond" : [
                        { "$ne" : ["$VolId", "$SupId"] }, 
                        { "VolFullName" : "$VolFullName", "VolPeopleCount" : "$VolPeopleCount" }, 
                        null
                    ] 
                } 
            } 
        } 
}, 
{ "$project" : { "SupFullName" : "$_id.SupFullName", "Volunteers" : "$__agg0", "_id" : 0 } }