Фильтры MongoDB Changestream

В настоящее время используется MongoDB.Driver v2.11.0 в приложении .Net Core 3.1. Пытался прочитать значения из потока изменений и следил за документацией здесь:

https://mongodb.github.io/mongo-csharp-driver/2.11/reference/driver/change_streams/

Моя проблема в том, что я пытаюсь получить только объекты с определенным типом и обновленным полем, но не могу заставить работать оба фильтра. Я могу заставить измененный поток захватывать только те объекты, которые имеют тип Z из полного документа, но не могу заставить какие-либо фильтры updateDescription.updatedFields работать должным образом.

Объект

public class Abc
{
    [BsonElement("d")]
    public D D{ get; set; }
    [BsonElement("e")]
    public E E{ get; set; }
}

public class D
{
    [BsonElement("type")]
    public string Type{ get; set; }
}

public class E
{
    [BsonElement("e")]
    public F F{ get; set; }
}

public class F
{
    [BsonElement("status")]
    public string Status { get; set; }
}

Итак, после подключения к mongo и получения коллекции вот код для настройки потока изменений.

protected ChangeStreamOptions _changeStreamOptions => new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup };

public IChangeStreamCursor<ChangeStreamDocument<Abc>> GetChangeStreamCursor()
{
    return _collection.Watch(ConfigurePipeline(), _changeStreamOptions);
}

private PipelineDefinition<ChangeStreamDocument<Abc>, ChangeStreamDocument<Abc>> ConfigurePipeline()
{
    List<IPipelineStageDefinition> pipeline = new List<IPipelineStageDefinition>();
    pipeline.Add(PipelineStageDefinitionBuilder.Match(ConfigureFilters()));
    return pipeline;
}

private FilterDefinition<ChangeStreamDocument<Abc>> ConfigureFilters()
{
  var builder = Builders<ChangeStreamDocument<Abc>>.Filter;

  //here is where I build the filters and having the issues.
  //if its just based on the object type It works.

  return builder.Eq("fullDocument.d.type", "z");
}

Это работает, и у вас нет проблем с получением только обновленных объектов с типом Z. Если я попытаюсь тогда также добавить фильтр, чтобы возвращать только объекты Z, у которых было обновлено поле Status до определенного типа.

Вот что я для этого пробовал:

builder.Eq("fullDocument.d.type", "z") & builder.AnyEq(x => x.UpdateDescription.UpdatedFields.Values, "Action");

builder.Eq("updateDescription.updatedFields.e.f.status", "Action");

builder.Eq("e.f.status", "Action");

Приложение будет работать с этим, но никогда не получит никаких изменений.

Также пробовал смотреть только на обновленные поля, поскольку UpdateDescription.UpdatedFields - это массив.

builder.ElemMatch(x => x.UpdateDescription.UpdatedFields, x => x.Name == "e.f.status" && x.Value == "Action")

Это не работает в основной программе с этой ошибкой

Unable to determine the serialization information for x => x.UpdateDescription.UpdatedFields.'

Проще говоря, мне нужно создать поток изменений и получить обратно только те объекты, которые имеют определенный тип свойства в полном документе и где другое свойство было обновлено до определенного типа.

Любая помощь будет оценена по достоинству!

Изменить обновление:

Если я изменю типы на BsonDocument, я могу передать это как конвейер, и он будет работать:

Итак, я работал с BsonObject и использовал это:

var filter = "{ $and: [ { operationType: 'update' }, " +
"{ 'fullDocument.d.type' : 'z'}" +
"{ 'updateDescription.updatedFields': { 'e.f.status': 'Action' } } ] }";

Но я бы хотел, чтобы он оставался напечатанным, если это возможно.


person Luney1788    schedule 15.09.2020    source источник
comment
Сначала заставьте это работать в оболочке mongo, если вам трудно удалить все, что связано с .net из вопроса, и оставить только команды оболочки.   -  person D. SM    schedule 16.09.2020
comment
Согласитесь с вышеизложенным, также в отношении: This fails in the program main with this error, попробуйте использовать BsonDocument вместо Abc (или любые другие классы). Это позволит избежать проблем с сериализацией, по крайней мере, вначале.   -  person dododo    schedule 16.09.2020
comment
Итак, я заставил его работать с BsonObject и использовать это: var filter = {$ and: [{operationType: 'update'}, + {'fullDocument.d.type': 'z'} + {'updateDescription.updatedFields': {'efstatus': 'Действие'}}]}; См. Редактирование выше для форматирования.   -  person Luney1788    schedule 16.09.2020
comment
см. также этот пример github.com/mongodb/mongo-csharp-driver/blob/master/tests/. Вы должны иметь возможность использовать набранный вами способ вместо BsonDocument в этой строке github.com/mongodb/mongo-csharp-driver/blob/master/tests/   -  person dododo    schedule 16.09.2020


Ответы (1)


Итак, я нашел решение, которое работает для меня так, как я описал выше.

private FilterDefinition<ChangeStreamDocument<Abc>> ConfigureFilters()
{
    var builder = Builders<ChangeStreamDocument<Abc>>.Filter;

    var filters = builder.And(builder.Eq("fullDocument.d.type", "z") & new BsonDocument("e.f.status", new BsonDocument("$eq", "Action")));

    return filters;
}
person Luney1788    schedule 16.09.2020