FilterDefinitionBuilder

FilterDefinitionBuilder

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

过去使用其他流利的接口,我以为我们可以简单地通过生成器来添加所需数量的过滤器,直到我准备好执行查询为止,然后我会调用.Build()命令,这最终将使我FilterDefinition对象。

但是,当我尝试组合Eq()调用时,它只是立即转换为FilterDefinition,而不是将其保留为FilterDefinitionBuilder直到时间到了。这似乎是Mongo不可扩展和短视的,因为添加.Build()功能可以使您以更灵活的方式链接命令。

首先,以这种方式做出决定的背后有任何理由。我想了解为什么这样做是因为我知道人们不会随便做出这些决定。

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

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

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


然后,我将使用包装函数调用此函数,而不是调用静态Builders<CosmosDocumentType>.Filter,将调用实用程序函数将其包装并返回FilterDefinitionBuilder对象,可以向其中添加更多过滤器。

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

拥有此.Build()还将使我能够查询集合中所有未删除的文档,而不必添加更多过滤器,因为目前看来,这是在FilterDefinitionBuilderFilterDefinition之间进行转换的唯一方法。

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

如果有一种方法可以将现有过滤器从FilterDefinition中拉出,则可能也有帮助。

最佳答案

据我了解,您需要用基本过滤器装饰所有过滤器。您可以使用多种方法进行操作,下面列出了三种方法。

假设您的基本过滤条件如下:

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


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

var filter01 = Builders<BsonDocument>.Filter.Eq("value", 1);
var filter02 = Builders<BsonDocument>.Filter.Eq("value", 2);


然后:


我们可以继续使用具有基本过滤器的高阶装饰器函数,然后返回一个函数,该函数在其他过滤器上的应用将导致使用基本过滤器装饰的过滤器。


它的实现很简单,如下所示:

public static Func<FilterDefinition<T>, FilterDefinition<T>>
  DecoratedFilter<T>(FilterDefinition<T> baseFilter) =>
    filter => baseFilter & filter;


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

var decorate = DecoratedFilter(baseFilter);

var decoratedFilter01 = decorate(filter01);
var decoratedFilter02 = decorate(filter02);



另一种方法是让您自己具有扩展方法:


public static FilterDefinition<T>
  Decorate<T>(this FilterDefinition<T> firstFilter,
              FilterDefinition<T> secondFilter) =>
    firstFilter & secondFilter;


可以如下使用:

var decoratedFilter01 = filter01.Decorate(baseFilter);
var decoratedFilter02 = filter02.Decorate(baseFilter);



您可以根据您的特定用例对基本过滤器进行硬编码,并可以实现如下:


public static readonly FilterDefinition<BsonDocument> BaseFilter = ...

public static FilterDefinition<BsonDocument>
  WithBaseFilter(this FilterDefinition<BsonDocument> filter) =>
    BaseFilter & filter;


然后只需将其用作:

var decoratedFilter01 = filter01.WithBaseFilter();
var decoratedFilter02 = filter02.WithBaseFilter();

07-24 14:03