MongoDb中的bucket模式是处理大型无界数组的最佳方式吗



我正在为MERN堆栈应用程序(关注/取消关注用户(实现社交功能,并试图提出一个好的MongoDB解决方案,以避免潜在的大型无界追随者阵列的问题。具体来说,我希望避免:

  • MongoDB必须在磁盘上移动一个大型跟随数组,并在其变大时重建索引
  • 如果用户拥有大量粉丝(>100万(,则达到1600亿bson限制
  • 通过分页查询/返回关注者以显示时,或计算/显示关注者计数时,性能缓慢

从Ive研究的所有内容来看,使用桶模式方法似乎是最好的解决方案。。。我发现了两篇关于这方面的好文章:https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-1https://www.mongodb.com/blog/post/paging-with-the-bucket-pattern--part-2

我已经开始这样对待它了。。。追随者模型:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const FollowerSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
// creating an array of followers
followers: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user',
},
datefol: {
type: Date,
default: Date.now,
},
},
],
count: {
type: Number,
},
createdate: {
type: Date,
default: Date.now,
required: true,
},
});
module.exports = Follower = mongoose.model('follower', FollowerSchema);

在Node.js api中升级,为数组bucket添加一个follower(每个bucket将包含100个followers(:

const follow = await Follower.updateOne(
{ user: req.params.id, count: { $lt: 100 } },
{
$push: {
followers: {
user: req.user.id,
datefol: Date.now(),
},
},
$inc: { count: 1 },
$setOnInsert: { user: req.params.id, createdate: Date.now() },
},
{ upsert: true }
);

基本上,每次添加追随者时,都会将他们添加到发现的第一个包含少于100个追随者的桶中(按计数跟踪(。

这是处理潜在大型阵列的最佳方法吗?我担心的是:

  • 如果有人取消关注用户,并且应用程序运行$pull将关注者从其中一个bucket中的数组中删除。。。那么多个桶可以包含少于100个追随者。新的关注者将不再添加到最新的bucket中,因此稍后在查询并尝试根据最新的by bucket createdate返回关注者时。。。一些最新的追随者可能在一个旧的桶里,没有正确返回。上面的文章提到了MongoDb 4.2中引入的一些富有表现力的更新指令,它们解决了这个问题,但我并不清楚如何解决
  • 如果我通过返回用户的所有follower bucket并按followdate排序来纠正这一点。。。如果一个人有大量的追随者,这似乎会变得非常缓慢
  • 如果我想从最新的开始分页并每页返回100个关注者,那么这种方法是如何工作的呢?我是否应该在模型中添加一个页码条目,并在每次创建bucket时以某种方式增加它(第一个bucket包含页码1,下一个页码2等(,然后在前端,如果用户跳到跟随页面500,则运行查询以提取bucket 500

bucket模式不是您公开的案例的完美匹配。

最适合您需求的模式是异常模式https://www.mongodb.com/blog/post/building-with-patterns-the-outlier-pattern

您的案例实际上与本文中的示例相同。

最新更新