Как связать FilterDefinitionBuilders в драйвере Mongo.Net - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть фильтр, который я хотел бы добавить к каждому из моих запросов в качестве основы для любого из моих запросов, которые я собираюсь выполнить в базе данных.Это будет означать, что мне не нужно добавлять фильтр (filter.Eq("deleted", false) & filter.Eq("another query", null) при каждом вызове, который я совершаю в мою коллекцию.

Используя в прошлом другие свободно распространяемые интерфейсы, я предположил, что мы могли бы просто передать конструктордобавив столько фильтров, сколько мне нравится, пока я фактически не буду готов выполнить запрос, а затем я вызову команду .Build(), и это, наконец, даст мне мой FilterDefinition объект.

Однако, когда я пытаюсь объединитьEq() вызывает, что он просто конвертируется в FilterDefinition сразу, вместо того, чтобы оставить его как FilterDefinitionBuilder до тех пор, пока не настало время. Это кажется довольно нерастяжимым и недальновидным для Монго, так как добавление функциональности .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() также позволило бы мне запрашивать все документы в коллекции, которые не были удалены, без добавления дополнительных фильтров, потому что в настоящее время это, кажется, единственный способ конвертировать между FilterDefinitionBuilderи FilterDefinition.

Другой альтернативой является написание моей собственной обертки Fluent вокруг функциональности и пропустите ее через FilterDefinitionBuilder в конце, когда я убедился, что у меня есть все фильтры на месте.

Если есть способ вытащить существующие фильтры из FilterDefinition, это также может помочь.

1 Ответ

2 голосов
/ 03 апреля 2019

Насколько я понимаю, вам нужно украсить все ваши фильтры базовым фильтром . Вы можете выполнить, используя различные подходы, и я перечислю три ниже.

Допустим, у вас есть следующее для базового фильтра:

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. Мы можем иметь функцию декоратора высшего порядка , которая принимает базовый фильтр и возвращает функцию, применение которой к другим фильтрам приведет к фильтру, который будет украшен базовым фильтром.

Его реализация проста следующим образом:

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