如何在 C# 中使用 mongo 驱动程序按条件排序
How to sort by condition using the mongo driver in c#
我一直在关注 mongo 驱动程序 (2.4) 文档,但目前正在尝试对排序设置条件。
按照文档,我得到了一个 AsQueryable 实例,并使用了带有传入表达式的 where 函数。在我想按条件而不是字段进行排序之前,它工作正常。
我想通过以下方式订购:
db.child.AsQueryable().Where(expression).OrderBy(x=> x.parentId == someParentId);
这应该类似于 linq
SELECT * FROM child
ORDER BY
CASE parentId
WHEN someParentId THEN 1
ELSE 2 END,
parentId;
但是目前,在 运行 OrderBy 条件之后,我相信它正在评估表达式,因为从调试器中我可以看到表达式的变化,如下所示:
所以两个主要问题是:
- 如何使用 .net mongo 驱动程序按布尔表达式排序。
- 为什么表达式被转换为屏幕截图中所示?
如 MongoDB C# 驱动程序文档所述(来自粘贴的 link):
The driver contains an implementation of LINQ that targets the aggregation framework.
因此聚合框架中必须有相应的操作才能从 LINQ 转换。您调用 .AsQueryable()
这意味着您可以使用 LINQ 语法构建表达式,但是当需要转换为聚合框架时它会失败。不幸的是,您不能在 $sort 中使用表达式,这就是您的代码将失败的原因。
要解决此问题,您可以使用 $addFields 阶段添加一个附加字段 MatchesParent
并按此字段排序。
假设您的模型由以下 class 表示:
public class Model
{
[BsonId]
public ObjectId Id { get; set; }
public string ParentId { get; set; }
// some other properties
}
您可以添加以下内容class:
public class ModelResult: Model
{
public bool MatchesParent { get; set; }
}
然后您可以将 $addFields
定义为 PipelineStageDefinition
和 nameof
运算符以保持其强类型:
PipelineStageDefinition<Model, ModelResult> addFields = new BsonDocument() {
{ "$addFields", new BsonDocument() {
{ nameof(ModelResult.MatchesParent), new BsonDocument() {
{ "$eq", new BsonArray() { "$" + nameof(Model.ParentId), someParentId } }
}
}
}
}
};
var result = Col.Aggregate()
.Match(expression)
.AppendStage(addFields)
.SortByDescending(x => x.MatchesParent)
.ToList();
我一直在关注 mongo 驱动程序 (2.4) 文档,但目前正在尝试对排序设置条件。
按照文档,我得到了一个 AsQueryable 实例,并使用了带有传入表达式的 where 函数。在我想按条件而不是字段进行排序之前,它工作正常。
我想通过以下方式订购:
db.child.AsQueryable().Where(expression).OrderBy(x=> x.parentId == someParentId);
这应该类似于 linq
SELECT * FROM child
ORDER BY
CASE parentId
WHEN someParentId THEN 1
ELSE 2 END,
parentId;
但是目前,在 运行 OrderBy 条件之后,我相信它正在评估表达式,因为从调试器中我可以看到表达式的变化,如下所示:
所以两个主要问题是:
- 如何使用 .net mongo 驱动程序按布尔表达式排序。
- 为什么表达式被转换为屏幕截图中所示?
如 MongoDB C# 驱动程序文档所述(来自粘贴的 link):
The driver contains an implementation of LINQ that targets the aggregation framework.
因此聚合框架中必须有相应的操作才能从 LINQ 转换。您调用 .AsQueryable()
这意味着您可以使用 LINQ 语法构建表达式,但是当需要转换为聚合框架时它会失败。不幸的是,您不能在 $sort 中使用表达式,这就是您的代码将失败的原因。
要解决此问题,您可以使用 $addFields 阶段添加一个附加字段 MatchesParent
并按此字段排序。
假设您的模型由以下 class 表示:
public class Model
{
[BsonId]
public ObjectId Id { get; set; }
public string ParentId { get; set; }
// some other properties
}
您可以添加以下内容class:
public class ModelResult: Model
{
public bool MatchesParent { get; set; }
}
然后您可以将 $addFields
定义为 PipelineStageDefinition
和 nameof
运算符以保持其强类型:
PipelineStageDefinition<Model, ModelResult> addFields = new BsonDocument() {
{ "$addFields", new BsonDocument() {
{ nameof(ModelResult.MatchesParent), new BsonDocument() {
{ "$eq", new BsonArray() { "$" + nameof(Model.ParentId), someParentId } }
}
}
}
}
};
var result = Col.Aggregate()
.Match(expression)
.AppendStage(addFields)
.SortByDescending(x => x.MatchesParent)
.ToList();