MongoDb.Linq 条件聚合器的等效查询
MongoDb.Linq equivalent query for conditional aggregator
我按以下方式将我的数据与 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"
}
现在,通过阅读本文 ,我能够将上述查询转换为以下查询:
"$push": {
"$cond": [
{ "$ne": [ "$VolId", "$SupId" ] },
{
"VolFullName": "$VolFullName",
"VolPeopleCount": "$VolPeopleCount"
},
null
]
}
这给了我想要的结果。我想知道如何(如果可能的话)指示 csharp 驱动程序生成如上所述的查询。提前致谢!
编辑: 按照@mickl 的建议,我能够生成一个条件 $push
(以及一个条件 $sum
),但结果并不像预期的。假设我的 collection:
中有以下文档
{ 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" } }
这里的N
、I
、FN
、S
和C
分别表示姓名、id、全名、主管和创建者。因此,正如您所看到的,主管 S_1
正在监督每个文档,已经创建了 3 个文档,并且有 6 个文档由 2 个其他创建者创建,他们也受到 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)
]
}
}
谢谢!
您可以 运行 Select
并在 LINQ 语句中使用三元运算符:
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 } }
我按以下方式将我的数据与 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"
}
现在,通过阅读本文
"$push": {
"$cond": [
{ "$ne": [ "$VolId", "$SupId" ] },
{
"VolFullName": "$VolFullName",
"VolPeopleCount": "$VolPeopleCount"
},
null
]
}
这给了我想要的结果。我想知道如何(如果可能的话)指示 csharp 驱动程序生成如上所述的查询。提前致谢!
编辑: 按照@mickl 的建议,我能够生成一个条件 $push
(以及一个条件 $sum
),但结果并不像预期的。假设我的 collection:
{ 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" } }
这里的N
、I
、FN
、S
和C
分别表示姓名、id、全名、主管和创建者。因此,正如您所看到的,主管 S_1
正在监督每个文档,已经创建了 3 个文档,并且有 6 个文档由 2 个其他创建者创建,他们也受到 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)
]
}
}
谢谢!
您可以 运行 Select
并在 LINQ 语句中使用三元运算符:
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 } }