简体   繁体   中英

Bucketing with MongoDB C# Driver

I'm trying to implement a technique known as bucketing in MongoDb (or so it was referred to as in a MongoDB workshop) and it uses the Push and Slice to achieve this. This is to achieve a user feed system similar to that of twitter/facebook.

Essentially I have a document with an array of items (feed items). I want to create a new document when this number of items reaches a certain number for a user.

So, if the latest userFeed document's collection has 50 items, i want a new document to be created and the new item to be inserted into the item array of the newly created document.

This is the code i have thus far:

var update = Builders<UserFeed>
                    .Update
                    .CurrentDate(x => x.DateLastUpdated)
                    .PushEach(x =>
                        x.Items,
                        new List<FeedItemBase> { feedItem },
                        50);

                var result = await Collection.UpdateOneAsync(x =>
                    x.User.Id == userFeedToWriteTo,
                    update,
                    new UpdateOptions { IsUpsert = true }
                    ).ConfigureAwait(false);

...

But it does not appear to create a new document, or even insert the item into the existing document's array. I thought the creation of the new document would be handled by this

new UpdateOptions { IsUpsert = true }

but apparently not. Any help would be greatly appreciated

So after having written out the problem and saying it out loud a few times i realised what the problem was.

I needed a counter on the main userfeed document which needed to be incremented every time an item was added (a feed item was posted). And in my query to perform the update/upsert i just needed to check for < 50. After which, everything works as expected. Here is the corrected code

var update = Builders<UserFeed>
                    .Update
                    .CurrentDate(x => x.DateLastUpdated)
                    .PushEach(x =>
                        x.Items,
                        new List<FeedItemBase> { feedItem },
                        50)
                        .Inc(x => x.Count, 1);

                var result = await Collection.UpdateOneAsync(x =>
                    x.User.Id == userFeedToWriteTo && x.Count < 50,
                    update,
                    new UpdateOptions { IsUpsert = true }
                    ).ConfigureAwait(false);

And as long as the count is NOT corrected if a user feed item is deleted from the items array, everything should work as expected. However, problems will arise if you modify the count on removal because you will end up with items added to previous documents and you will need to perform sorts after you unwind the data, which at present, i do not need to. It does mean you will end up with some documents with less than 50 items in the array, but to me that doesn't really matter.

I hope this helps someone trying to implement a similar solution in c#.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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