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

时间:2019-04-02 14:52:14

标签: c# mongodb mongodb-.net-driver

我有一个过滤器,我想将其添加到每个查询中,作为我将要在数据库上执行的任何查询的基础。这意味着我不必记住要在我对收藏集的每次调用中添加过滤器(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()还将使我能够查询集合中所有未删除的文档而不必添加更多过滤器,因为目前看来,这是在{{1}之间进行转换的唯一方法}和FilterDefinitionBuilder

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

如果有一种方法可以将现有过滤器从FilterDefinitionBuilder中拉出来,这也可能会有所帮助。

1 个答案:

答案 0 :(得分:2)

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

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

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);

然后:

  1. 我们可以继续使用具有高阶 decorator 函数,该函数带有基本过滤器并返回一个函数,该函数在其他过滤器上的应用将导致该过滤器将被基本过滤器修饰。 / li>

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

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);
  1. 另一种方法是让您自己具有扩展方法:
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);
  1. 您可以根据您的特定用例对基本过滤器进行硬编码,并可以实现如下:
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();