简体   繁体   English

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

[英]How to chain FilterDefinitionBuilders in Mongo.Net Driver

I have a filter that I would like to add to each of my queries as a basis to any of my queries that I am going to perform on the database. 我有一个过滤器,我想将其添加到每个查询中,作为我将要在数据库上执行的任何查询的基础。 This will mean that i don't have to remember to add a filter ( filter.Eq("deleted", false) & filter.Eq("another query", null) on every call i make to my collection. 这意味着我不必记住在我对集合的每次调用中都添加一个过滤器( filter.Eq("deleted", false) & filter.Eq("another query", null)

Using other fluent interfaces in the past i assumed that we could simply pass the builder around adding as many filters as i liked until I was actually ready to perform the query and then i would call a .Build() command and this would finally give me my FilterDefinition object. 过去使用其他流利的接口,我假设我们可以简单地通过构建器来添加我喜欢的过滤器,直到我准备好执行查询为止,然后我将调用.Build()命令,这最终将给我我的FilterDefinition对象。

However when I try combining the Eq() calls it simply converts to a FilterDefinition straight away rather than leaving it as a FilterDefinitionBuilder until it's time has come. 但是,当我尝试组合Eq()调用时,它只是立即转换为FilterDefinition ,而不是直到需要时才将其保留为FilterDefinitionBuilder This seems fairly inextensible and short sighted by the Mongo as adding a .Build() functionality would have allowed you to chain commands in a more flexible manner. 这似乎是Mongo不可.Build()和短视的,因为添加.Build()功能可以使您以更灵活的方式链接命令。

Firstly is there any reason behind the decision to do it in this manner. 首先,以这种方式做出决定的背后有任何理由。 I want to understand why it was done like this as I know that people don't just arbitrarily make these decisions. 我想了解为什么这样做是因为我知道人们不会随便做出这些决定。

Secondly, has anyone managed to write any extension methods that would help me with my current predicament that they wouldn't mind sharing. 其次,有没有人设法编写任何扩展方法来帮助我解决当前他们不介意共享的困境。

My first attempt was to include something like the following: 我的第一个尝试是包含以下内容:

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

Then i would call this to from a wrapper function that I would use instead of calling the static Builders<CosmosDocumentType>.Filter I would call a utility function that would wrap this and return a FilterDefinitionBuilder object that I can add some more filters to. 然后,我将从包装函数调用此函数,而不是调用静态Builders<CosmosDocumentType>.Filter我将调用一个实用程序函数,将其包装并返回一个FilterDefinitionBuilder对象,可以向其中添加更多过滤器。

Once complete I'd like to call a .Build() method and then be presented with a rather lovely and rather functional FilterDefinition object that will get what documents I want from the collection. 完成后,我想调用.Build()方法,然后为它提供一个相当可爱且功能强大的FilterDefinition对象,该对象将从集合中获取我想要的文档。

Having this .Build() would also allow me to query all documents in a collection that are not deleted without having to add more filters, because at present this seems to be the only way to convert between a FilterDefinitionBuilder and a FilterDefinition . 拥有这个.Build()还将使我能够查询集合中所有未删除的文档而不必添加更多过滤器,因为当前这似乎是在FilterDefinitionBuilderFilterDefinition之间进行转换的唯一方法。

The other alternative is writing my own Fluent wrapper around the functionality and run it through a FilterDefinitionBuilder at the end when I am satisfied that I have all of the filters in place. 另一种选择是围绕功能编写我自己的Fluent包装器,并在我对所有过滤器都安装到位感到满意时,最后通过FilterDefinitionBuilder运行它。

If there is a way to pull the existing filters out of a FilterDefinition that might also help. 如果有一种方法可以将现有过滤器从FilterDefinition中拉出,则可能也有帮助。

As I understand it, you need to decorate all your filters with a base filter . 据我了解,您需要使用基本过滤装饰所有过滤 You can carry out using various approaches and I list three below. 您可以使用多种方法进行操作,下面列出了三种方法。

Let's say you have the following for your base filter: 假设您的基本过滤条件如下:

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

And the following filters that you need to decorate: 以及您需要装饰的以下过滤器:

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

Then: 然后:

  1. We can go about having a higher-order decorator function that takes a base filter and returns a function whose application on other filters will result in a filter that will be decorated with the base filter. 我们可以继续使用具有基本过滤器的高阶装饰器函数,并返回一个函数,该函数在其他过滤器上的应用将导致使用基本过滤器装饰的过滤器。

Its implementation is simple as follows: 它的实现很简单,如下所示:

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

You can now use the DecoratedFilter() function to get a function and use it on your filters as follows: 现在,您可以使用DecoratedFilter()函数来获取一个函数并将其在过滤器上使用,如下所示:

var decorate = DecoratedFilter(baseFilter);

var decoratedFilter01 = decorate(filter01);
var decoratedFilter02 = decorate(filter02);
  1. Another approach is for you to have an extension method itself: 另一种方法是让您自己具有扩展方法:
public static FilterDefinition<T>
  Decorate<T>(this FilterDefinition<T> firstFilter,
              FilterDefinition<T> secondFilter) => 
    firstFilter & secondFilter;

It can be used as follows: 可以如下使用:

var decoratedFilter01 = filter01.Decorate(baseFilter);
var decoratedFilter02 = filter02.Decorate(baseFilter);
  1. You can hard-code the base filter based on your particular use case and can have an implementation as follows: 您可以根据您的特定用例对基本过滤器进行硬编码,并可以实现如下:
public static readonly FilterDefinition<BsonDocument> BaseFilter = ...

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

Then simply use it as: 然后只需将其用作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM