如何在 Mongo.Net 驱动程序中链接 FilterDefinitionBuilders

chu*_*its 0 c# mongodb mongodb-.net-driver

我有一个过滤器,我想将其添加到每个查询中,作为我要在数据库上执行的任何查询的基础。这意味着我不必记住添加过滤器(filter.Eq("deleted", false) & filter.Eq("another query", null)在我对集合进行的每次调用中。

过去使用其他流畅的接口,我假设我们可以简单地传递构建器,添加我喜欢的尽可能多的过滤器,直到我真正准备好执行查询,然后我会调用一个命令,.Build()这最终会给我我的FilterDefinition对象。

然而,当我尝试组合调用时,Eq()它只是立即转换为 a FilterDefinition,而不是将其保留为 aFilterDefinitionBuilder直到时间到来。这对于 Mongo 来说似乎相当不可扩展且目光短浅,因为添加.Build()功能将允许您以更灵活的方式链接命令。

首先,决定这样做有什么理由吗?我想了解为什么这样做,因为我知道人们不会随意做出这些决定。

其次,是否有人设法编写任何扩展方法来帮助我解决当前的困境,他们不介意分享。

我的第一次尝试是包含以下内容:

public static FilterDefinitionBuilder<TDocument>(this FilterDefinitionBuilder<TDocument> filter)
{
    var name = GetCollectionName<TDocument>();
    return filter.Eq("deleted", false);
}
Run Code Online (Sandbox Code Playgroud)

然后我会从一个包装函数中调用它,而不是调用静态Builders<CosmosDocumentType>.Filter函数,我会调用一个实用程序函数来包装它并返回一个FilterDefinitionBuilder我可以添加更多过滤器的对象。

完成后,我想调用一个.Build()方法,然后看到一个相当可爱且功能强大的FilterDefinition对象,它将从集合中获取我想要的文档。

有了这个.Build()还允许我查询集合中未删除的所有文档,而无需添加更多过滤器,因为目前这似乎是在 aFilterDefinitionBuilder和 a之间转换的唯一方法FilterDefinition

另一种选择是围绕功能编写我自己的 Fluent 包装器,并FilterDefinitionBuilder在最后当我对所有过滤器都已就位感到满意时运行它。

如果有一种方法可以将现有的过滤器从过滤器中取出,FilterDefinition那也可能会有所帮助。

Ama*_*tri 5

据我了解,您需要用基本过滤器来装饰所有过滤器。您可以使用各种方法来执行,我在下面列出了三种方法。

假设您的基本过滤器具有以下内容:

var builder = Builders<BsonDocument>.Filter;
var baseFilter = builder.Eq("deleted", false) & 
                 builder.Eq("another query", BsonNull.Value);
Run Code Online (Sandbox Code Playgroud)

以及您需要装饰的以下过滤器:

var filter01 = Builders<BsonDocument>.Filter.Eq("value", 1);
var filter02 = Builders<BsonDocument>.Filter.Eq("value", 2);
Run Code Online (Sandbox Code Playgroud)

然后:

  1. 我们可以使用一个高阶装饰器函数,它接受一个基本过滤器并返回一个函数,该函数在其他过滤器上的应用将产生一个将用基本过滤器装饰的过滤器。

其实现简单如下:

public static Func<FilterDefinition<T>, FilterDefinition<T>>
  DecoratedFilter<T>(FilterDefinition<T> baseFilter) =>
    filter => baseFilter & filter;
Run Code Online (Sandbox Code Playgroud)

您现在可以使用该DecoratedFilter()函数来获取函数并将其用于过滤器,如下所示:

var decorate = DecoratedFilter(baseFilter);

var decoratedFilter01 = decorate(filter01);
var decoratedFilter02 = decorate(filter02);
Run Code Online (Sandbox Code Playgroud)
  1. 另一种方法是让您拥有一个扩展方法本身:
public static FilterDefinition<T>
  Decorate<T>(this FilterDefinition<T> firstFilter,
              FilterDefinition<T> secondFilter) => 
    firstFilter & secondFilter;
Run Code Online (Sandbox Code Playgroud)

它可以按如下方式使用:

var decoratedFilter01 = filter01.Decorate(baseFilter);
var decoratedFilter02 = filter02.Decorate(baseFilter);
Run Code Online (Sandbox Code Playgroud)
  1. 您可以根据您的特定用例对基本过滤器进行硬编码,并可以按如下方式实现:
public static readonly FilterDefinition<BsonDocument> BaseFilter = ...

public static FilterDefinition<BsonDocument>
  WithBaseFilter(this FilterDefinition<BsonDocument> filter) =>
    BaseFilter & filter;
Run Code Online (Sandbox Code Playgroud)

然后简单地将其用作:

var decoratedFilter01 = filter01.WithBaseFilter();
var decoratedFilter02 = filter02.WithBaseFilter();
Run Code Online (Sandbox Code Playgroud)