数据库设计 – 使用MongoDB的类似Twitter的应用程序
我正在制作一个应用程序,它使用经典的“跟随”机制(Twitter使用的)和网络上的许多其他应用程序.我正在使用MongoDB.
不过,我的系统有所不同,用户可以跟随用户群.这意味着,如果您遵循一个群组,您将自动跟踪该群组成员的所有用户.当然,用户可以属于多个组. 这是我想出来的: >当用户A遵循用户B时,用户B的ID被添加到用户A的文档中的嵌入式数组(称为以下)
我可以改变设计并使用一个userfollow集合,它将执行与嵌入的以下文档相同的工作.我尝试的这种方法的问题是,在我以前使用的$或条件下,包含相同用户的两个组之后的用户将被列出两次.为了避免这种情况,我可以使用组或MapReduce,我实际上是这样做的,但是我很乐意避免这样做,使事情变得更简单.也许我只需要开箱即用.或者也许我尝试错误的方法.任何人都必须做类似的事情,并提出一个更好的解决方案? (这实际上是我的this older question的后续行动,我决定发表一个新的问题来更好地解释我的新情况,希望不是问题.) 解决方法
您有两种可能的方式,用户可以跟随另一个用户;直接或间接地通过组,在这种情况下,用户直接跟随组.我们开始在用户和组之间存储这些直接关系:
{ _id: "userA",followingUsers: [ "userB","userC" ],followingGroups: [ "groupX","groupY" ] } 现在,您可以直接或间接地快速找出用户A所关注的用户.为了实现这一点,您可以对用户A所关注的组进行非规范化.假设X和Y组定义如下: { _id: "groupX",members: [ "userC","userD" ] },{ _id: "groupY",members: [ "userD","userE" ] } 基于这些组和用户A具有的直接关系,您可以在用户之间生成订阅.订阅的来源与每个订阅一起存储.对于示例数据,订阅将如下所示: // abusing exclamation mark to indicate a direct relation { ownerId: "userA",userId: "userB",origins: [ "!" ] },{ ownerId: "userA",userId: "userC",origins: [ "!","groupX" ] },userId: "userD",origins: [ "groupX","groupY" ] },userId: "userE",origins: [ "groupY" ] } 您可以轻松地生成这些订阅,对单个用户使用map-reduce-finalize调用.如果一个组被更新,您只需要重新运行所有跟随该组的用户的map-reduce,并且订阅将再次被更新. 的map-reduce 以下map-reduce功能将生成单个用户的订阅. map = function () { ownerId = this._id; this.followingUsers.forEach(function (userId) { emit({ ownerId: ownerId,userId: userId },{ origins: [ "!" ] }); }); this.followingGroups.forEach(function (groupId) { group = db.groups.findOne({ _id: groupId }); group.members.forEach(function (userId) { emit({ ownerId: ownerId,{ origins: [ group._id ] }); }); }); } reduce = function (key,values) { origins = []; values.forEach(function (value) { origins = origins.concat(value.origins); }); return { origins: origins }; } finalize = function (key,value) { db.subscriptions.update(key,{ $set: { origins: value.origins }},true); } 然后,您可以通过在userA中指定查询来为单个用户运行map-reduce. db.users.mapReduce(map,reduce,{ finalize: finalize,query: { _id: "userA" }}) 几个注释: >在为该用户运行map-reduce之前,应删除用户的以前订阅. 我应该注意,这些map-reduce函数证明比我想到的更复杂,因为MongoDB不支持数组作为reduce函数的返回值.在理论上,功能可以简单得多,但与MongoDB不兼容.然而,如果您有必要,这个更复杂的解决方案可用于映射 – 在单个调用中减少整个用户集合. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |