MongoDB 4.4.4 更改流返回所有文档更新而不是过滤条件匹配一个? [英] MongoDB 4.4.4 change stream returns all document updates rather than filtered condition matched one?

查看:32
本文介绍了MongoDB 4.4.4 更改流返回所有文档更新而不是过滤条件匹配一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking for notifications of a single document's 'update' operation within a collection, supposedly when that particular document gets updated MongoDB would notify a 'watch' registered .net client, but the reality is MongoDB returns all documents with 'update' operations in the collection, no matter how the "match" condition of filter sets.

任何有 Change Stream 经验的人都可以提供帮助吗?这是 MongoDB 变更流的性质/设计吗?

Can anyone with Change Stream experience help? Is it the nature/design of MongoDB change stream?

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

Below is the test code pieces of .net C# client,

班级:

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

过滤条件管道:

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

更改事件流程例程:

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

从上面的例程来看,change事件并没有根据过滤条件工作,每次触发这个例程时,'change.FullDocument.UserName'实际上会打印出集合中得到'update'操作的每个文档,这很奇怪.

From the above routine, change events aren't working according to the filter conditions, every time this routine gets triggered, 'change.FullDocument.UserName' actually prints out every document in the collection that gets 'update' operation, which is quite weird.

推荐答案

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

i was able to get it to work with the following:

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

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

if you don't mind using a library, all of the above song and dance can be avoided and things can be distilled down to the following:

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

查看 MongoDB.Entities 文档了解更多信息.免责声明:我是该库的作者.

check out MongoDB.Entities docs for more info. disclaimer: i'm the author of that library.

这篇关于MongoDB 4.4.4 更改流返回所有文档更新而不是过滤条件匹配一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆