Я группирую свои данные с помощью 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
s не совпадает с ключом группы. Я ожидал, что драйвер сгенерирует условный $push
, но вместо этого он выдает простой:
"$push" : {
"VolFullName" : "$VolFullName",
"VolPeopleCount" : "$VolPeopleCount"
}
Теперь, прочитав этот сообщение, я смог преобразовать приведенный выше запрос в следующий:
"$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" } }
Здесь N
, I
, FN
, S
и C
означают имя, идентификатор, полное имя, руководитель и создатель соответственно. Итак, как вы можете видеть, руководитель 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 } }
@dcg, не могли бы вы отредактировать свой ответ и показать разницу между тем, что вы получаете, и тем, что вы ожидаете? Или, если это что-то, что меняет ожидания от этого вопроса, то, возможно, было бы лучше открыть новый. Спасибо !
Привет, я только что отредактировал свой вопрос. Можешь взглянуть? Спасибо!
@dcg Я думаю, что этот запрос становится немного сложным. Как насчет такого вывода: mongoplayground.net/p/6RePgYMMZUR ?
Мне пришлось прочитать документы, чтобы понять запрос (все еще новичок), и да, этот вывод соответствует моим потребностям. Но... как мне заставить драйвер c#
генерировать такой запрос?
Привет, спасибо за ваш ответ. Теперь я получаю желаемое условное выражение, но с
$_id.SupId
в операторе$ne
вместо$SupId
, что дает результаты, отличные от моего собственного запроса. Этоgroup
происходит от другогоselect
другогоgroup
. Любая идея, почему это происходит?