$ inc follower count,还是我应该使用聚合来跟踪它们?

我通过无限滚动的方式一次加载12个产品。

有时候,我可能想通过他们有多less追随者来分类。

以下是我跟踪每个产品有多less追随者。


下面是一个单独的收集,因为16mb的数据上限,以下的金额应该是无限的。

遵循模式:

var FollowSchema = new mongoose.Schema({ user: { type: mongoose.Schema.ObjectId, ref: 'User' }, product: { type: mongoose.Schema.ObjectId, ref: 'Product' }, timestamp: { type: Date, default: Date.now } }); 

遵循模式的产品:

 var ProductSchema = new mongoose.Schema({ name: { type: String, unique: true, required: true }, followers: { type: Number, default: 0 } }); 

每当用户关注/取消关注产品时,我都会运行此function:

 ProductSchema.statics.updateFollowers = function (productId, val) { return Product .findOneAndUpdateAsync({ _id: productId }, { $inc: { 'followers': val } }, { upsert: true, 'new': true }) .then(function (updatedProduct) { return updatedProduct; }) .catch(function (err) { console.log('Product follower update err : ', err); }) }; 

我的问题是:

1:产品中增加的“追随者”值是否有可能遇到某种错误,导致不匹配/不一致的数据?

2:最好是写一个聚合数来计算每个产品的追随者,否则会太昂贵/太慢?

最后,我可能会重写这个在graphDB,因为它似乎更适合,但现在 – 这是一个在掌握MongoDB的练习。

1如果在删除后插入或减less后增加,则这可能导致数据不一致。 例如,插入成功,但递增失败。

2直观地说,在这种情况下,聚合要比find的要昂贵得多。 我做了一个基准来certificate这一点。

首先随机生成1000个用户,1000个产品和10000个关注者。 然后,使用此代码进行基准testing。

 import timeit from pymongo import MongoClient db = MongoClient('mongodb://127.0.0.1/test', tz_aware=True).get_default_database() def foo(): result = list(db.products.find().sort('followers', -1).limit(12).skip(12)) def bar(): result = list(db.follows.aggregate([ {'$group': {'_id': '$product', 'followers': {'$sum': 1}}}, {'$sort': {'followers': -1}}, {'$skip': 12}, {'$limit': 12} ])) if __name__ == '__main__': t = timeit.timeit('foo()', 'from __main__ import foo', number=100) print('time: %f' % t) t = timeit.timeit('bar()', 'from __main__ import bar', number=100) print('time: %f' % t) 

输出:

 time: 1.230138 time: 3.620147 

创build索引可以加速查找查询。

 db.products.createIndex({followers: 1}) time: 0.174761 time: 3.604628 

如果您需要产品的名称等属性,则需要另一个O(n)查询。

我猜在数据放大的时候,聚合会慢得多。 如果需要,我可以在大规模的数据基准。

对于第一,如果该领域的唯一操作是递增和递减,我想你会没事的。 如果您开始复制该数据或由于某种原因在连接中使用该数据,则可能会遇到数据不一致的风险。

对于编号2,我build议你在mongo shell中运行这两种scheme来testing它们。 您也可以查看两个查询的单独解释计划 ,以了解哪一个更好。 我只是猜测,但似乎更新路线将performance良好。

另外,预期的数据量有所不同。 它可能在某种程度上performance得很好,但是在一百万条logging之后,另一条路线可能就是要走的路。 如果你有一个testing环境,这将是一件好事情来检查。

1)这依赖于应用程序层来强化一致性,这样就有可能导致不一致。 我会问的问题是:在这种情况下,一致性有多重要,有多大可能会有很大的不一致? 我的想法是,一个追随者的离开并不像尽可能快地使你的无限滚动负载来提高用户的体验一样重要。

2)也许值得看看performance,但如果我不得不猜测,我会说这种方法会慢下来。