MongoDB 4.4.4更改流返回所有文档更新而不是过滤条件匹配的更新?

MTA*_*MTA 6 .net c# mongodb xamarin.forms mongodb-.net-driver

我正在寻找集合中单个文档“更新”操作的通知,据说当该特定文档更新时,MongoDB 会通知“监视”注册的 .net 客户端,但实际情况是 MongoDB 返回具有“更新”操作的所有文档集合,无论过滤器集的“匹配”条件如何。

有变革流经验的人可以提供帮助吗?这是 MongoDB 变更流的本质/设计吗?

下面是.net C#客户端的测试代码片段,

班上:

public class UserInfo
{
        [BsonId, BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }

        [BsonElement("UserName", Order = 1), BsonRepresentation(BsonType.String)]
        public string UserName { get; set; }

        [BsonElement("Password", Order = 2), BsonRepresentation(BsonType.String)]
        public string Password { get; set; }

        [BsonElement("LastName", Order = 3), BsonRepresentation(BsonType.String)]
        public string LastName { get; set; }

        [BsonElement("FirstName", Order = 4), BsonRepresentation(BsonType.String)]
        public string FirstName { get; set; }

        [BsonElement("Email", Order = 5), BsonRepresentation(BsonType.String)]
        public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

过滤条件管道:

collection = myDB.GetCollection<UserInfo>("Users");
var options = new ChangeStreamOptions
            {
                FullDocument = ChangeStreamFullDocumentOption.UpdateLookup,
            };
var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<UserInfo>>();
pipeline.Match(g => g.OperationType == ChangeStreamOperationType.Update)
        .Match(o => o.FullDocument.UserName.Contains("Alice"))
        .Match(t => t.UpdateDescription.UpdatedFields.ToString().Contains(nameof(UserInfo.Password)));

Task watchTask = WatchCollection();
Run Code Online (Sandbox Code Playgroud)

更改事件处理例程:

private static async Task WatchCollection()
{
            var cursor =  await collection.WatchAsync(pipeline, options);
            Debug.WriteLine("ChangeStream started.");
            
            await cursor.ForEachAsync(change =>
            {
                Debug.WriteLine("Matched UserName: " + change.FullDocument.UserName);
            });
}
Run Code Online (Sandbox Code Playgroud)

从上面的例程来看,更改事件并没有根据过滤条件起作用,每次触发该例程时,“change.FullDocument.UserName”实际上都会打印出集合中获得“更新”操作的每个文档,这很奇怪。

Dĵ *_*ΛψΚ 3

我能够让它与以下内容一起工作:

var options = new ChangeStreamOptions
{
    FullDocument = ChangeStreamFullDocumentOption.UpdateLookup,
    BatchSize = 1
};

var filter = Builders<ChangeStreamDocument<UserInfo>>
    .Filter.Where(x =>
        x.OperationType == ChangeStreamOperationType.Update &&
        x.FullDocument.UserName.Contains("Alice"));

filter &= Builders<ChangeStreamDocument<UserInfo>>.Filter.Exists("updateDescription.updatedFields.Password");

var pipeline = new IPipelineStageDefinition[]
{
    PipelineStageDefinitionBuilder.Match(filter)
};

using (var cursor = await collection.WatchAsync<ChangeStreamDocument<UserInfo>>(pipeline, options))
{
    while (await cursor.MoveNextAsync())
    {
        foreach (var info in cursor.Current)
        {
            Console.WriteLine("Updated: " + info.FullDocument.UserName);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您不介意使用图书馆,则可以避免上述所有歌曲和舞蹈,并且可以将事情简化为以下内容:

var watcher = DB.Watcher<UserInfo>("on-alice-updates-password");

watcher.Start(
    eventTypes: EventType.Updated,
    filter: b => b.Where(x => x.FullDocument.UserName == "Alice") &
                 b.Exists("updateDescription.updatedFields.Password"));

watcher.OnChanges += docs =>
{
    foreach (var doc in docs)
        Console.WriteLine("Updated: " + doc.UserName);
};
Run Code Online (Sandbox Code Playgroud)

查看MongoDB.Entities文档以获取更多信息。免责声明:我是该库的作者。