使用 C# 驱动程序在 mongodb 中查找具有最高计算值的文档
Find document with highest calculated value in mongodb using c# driver
有没有办法找到 mongo db 中计算值最高的文档?
我有一个数组属性,它由 int 的 1-5 组成。我想找到均值最高的文档。
像这样使用常规 Linq:
var entityWithCalculatedMax = collection.OrderByDescending(x => x.Grade.Sum() / x.Grade.Count()).First();
有什么建议吗?
(我试图直接在数据库中执行此操作,因为我不想检索所有文档来获取文档)
遗憾的是,这无法使用 LINQ 语法完成。使用 the official "Aggregation Pipeline" documentation.
中记录的规范聚合语法更容易(也更具体)
示例输入:
{ _id: 1, Grades: [ 1, 1 ] }
{ _id: 2, Grades: [ 2, 3, 4 ] }
{ _id: 3, Grades: [ 5 ] }
想法是在聚合管道中有四个步骤:
Unwind 每个 Grades
数组:对于每个文档,这将创建 n 个文档,其中 n 是每个文件只有一个等级的等级数:
结果:
{ _id: 1, Grades: 1 }
{ _id: 1, Grades: 1 }
{ _id: 2, Grades: 2 }
{ _id: 2, Grades: 3 }
{ _id: 2, Grades: 4 }
{ _id: 3, Grades: 5 }
按 ID 对文档进行分组,汇总 a) 平均 属性(您的计算)和 b) 新成绩 属性 来恢复我们的数组:
结果:
{ _id: 1, Average: 1.0, Grades: [ 1, 1 ] }
{ _id: 2, Average: 3.0, Grades: [ 2, 3, 4 ] }
{ _id: 3, Average: 5.0, Grades: [ 5 ] }
按平均值对文档排序。
结果:同上,不知何故已经下单了
限制 为 1 个文档,因为您只需要第一个结果。
我们可以将其转换为 JSON 并针对我们的数据库执行:
db.gradeDocs.aggregate(
[
{ $unwind: "$Grades" },
{
$group: {
_id: "$_id",
Average: { $avg: "$Grades" },
Grades: { $push: "$Grades" }
}
},
{ $sort: { "Average": 1 } },
{ $limit: 1 }
]
)
好的,现在我们如何使用 C# 驱动程序执行此操作?语法有点冗长,但本质上是一样的:
var aggregateArgs = new AggregateArgs();
aggregateArgs.Pipeline =
new[]
{
new BsonDocument("$unwind", "$Grades"),
new BsonDocument("$group",
new BsonDocument
{
{"_id", "$_id"},
{"Average", new BsonDocument("$avg", "$Grades")},
{"Grades", new BsonDocument("$push", "$Grades")},
}),
new BsonDocument("$sort", new BsonDocument("Average", 1)),
new BsonDocument("$limit", 1),
};
var resultId = collection
.Aggregate(aggregateArgs)
.Single()["_id"]
.AsObjectId;
有没有办法找到 mongo db 中计算值最高的文档?
我有一个数组属性,它由 int 的 1-5 组成。我想找到均值最高的文档。
像这样使用常规 Linq:
var entityWithCalculatedMax = collection.OrderByDescending(x => x.Grade.Sum() / x.Grade.Count()).First();
有什么建议吗?
(我试图直接在数据库中执行此操作,因为我不想检索所有文档来获取文档)
遗憾的是,这无法使用 LINQ 语法完成。使用 the official "Aggregation Pipeline" documentation.
中记录的规范聚合语法更容易(也更具体)示例输入:
{ _id: 1, Grades: [ 1, 1 ] }
{ _id: 2, Grades: [ 2, 3, 4 ] }
{ _id: 3, Grades: [ 5 ] }
想法是在聚合管道中有四个步骤:
Unwind 每个
Grades
数组:对于每个文档,这将创建 n 个文档,其中 n 是每个文件只有一个等级的等级数:结果:
{ _id: 1, Grades: 1 } { _id: 1, Grades: 1 } { _id: 2, Grades: 2 } { _id: 2, Grades: 3 } { _id: 2, Grades: 4 } { _id: 3, Grades: 5 }
按 ID 对文档进行分组,汇总 a) 平均 属性(您的计算)和 b) 新成绩 属性 来恢复我们的数组:
结果:
{ _id: 1, Average: 1.0, Grades: [ 1, 1 ] } { _id: 2, Average: 3.0, Grades: [ 2, 3, 4 ] } { _id: 3, Average: 5.0, Grades: [ 5 ] }
按平均值对文档排序。
结果:同上,不知何故已经下单了
限制 为 1 个文档,因为您只需要第一个结果。
我们可以将其转换为 JSON 并针对我们的数据库执行:
db.gradeDocs.aggregate(
[
{ $unwind: "$Grades" },
{
$group: {
_id: "$_id",
Average: { $avg: "$Grades" },
Grades: { $push: "$Grades" }
}
},
{ $sort: { "Average": 1 } },
{ $limit: 1 }
]
)
好的,现在我们如何使用 C# 驱动程序执行此操作?语法有点冗长,但本质上是一样的:
var aggregateArgs = new AggregateArgs();
aggregateArgs.Pipeline =
new[]
{
new BsonDocument("$unwind", "$Grades"),
new BsonDocument("$group",
new BsonDocument
{
{"_id", "$_id"},
{"Average", new BsonDocument("$avg", "$Grades")},
{"Grades", new BsonDocument("$push", "$Grades")},
}),
new BsonDocument("$sort", new BsonDocument("Average", 1)),
new BsonDocument("$limit", 1),
};
var resultId = collection
.Aggregate(aggregateArgs)
.Single()["_id"]
.AsObjectId;