2015-09-20 55 views
0

假设我有一个有成千上万用户的服务,并且我想发布他们可以查看的新闻提醒。一旦他们看到一个,它被标记为看到(显然,只为那个用户)。MongoDB - 如何处理阅读新闻提醒的用户

我想我知道这个答案,但是在新闻项目上存储一个已经看到它的用户列表是否更好?或者,最好在用户文档上存储他们看到的所有新闻项目的列表?

我假设后者更好,主要是因为如果我有20,000用户,这意味着如果他们都看到了特定的新闻提醒,那么我有一个存储在该新闻提醒文档中的20,000个ID的数组,这可能不好。但这种结构似乎更好:

{ 
    email: '[email protected]', 
    name: 'Person', 
    seenNews: [ 
    'TTJGGiPsTqqLio4sf', 
    'vhePmuShra3MSzYsu', 
    'JKFqqCKDmtuuoQBXu', 
    'gCFyzu8BAihj8NnXB' 
    ] 
} 

我可能不会有超过几百新闻项目多,再加上我可以随时回去,反正删除旧的。

还是有更好的方法来处理这个问题吗?

回答

1

鉴于你有新闻

{ 
    _id: "Fubar2.0", 
    title: "Fubar 2.0 released" 
} 

和用户

{ 
    _id: "12345", 
    name: "CoolName" 
} 

存储什么在以上任一车型被视为迟早会超过16MB的文件BSON大小限制。此外,使用mmapv1存储引擎不能有效处理增加的文档,该引擎仍然是默认设置。

结论:你需要在单独的文档阅读新闻存储看到集合中:

{ 
    _id: { 
    newsitem: "Fubar2.0", 
    user:"12345" 
    } 
} 

由于我们具有复合_id的看到,这是自动索引(并且只要在RAM中尽可能),查询非常有效。

的问题是显而易见的:你需要两个查询由用户来获取新闻看不见

var seen = new Array() 
db.seen.find({"_id.user":"12345"},{_id:1}).forEach(
    function(doc){ 
    seen.push(doc._id.news); 
    } 
) 
var unseen = db.news.find({_id: {$nin: seen}}) 

虽然这个工程恕我直言是描述的情况下的适当的解决方案,“看不见”的查询是不是很高效。

根据不同的使用情况下,你可以比较像这样的东西,为用户

{ 
    _id:"12345", 
    name: "CoolName", 
    lastSeen: ISODate("2015-05-05T03:26:36Z") 
} 

和新闻这样

{ 
    _id:{ 
    title:"FuBar 2.0 released", 
    date: ISODate("2015-05-05T03:46:00Z") 
    } 
} 

因此,当用户登录,您已加载的用户去文件,对吗?有了这个,你可以得到所有的新闻,他或她可能还没有与

db.news.find({"_id.date":{$gte: user.lastSeen} }) 

看到诚然,你不能真正检查哪个用户已经看到了这条新闻,但如果我们的目标是确保用户在上次访问后收到所有新闻,后一种解决方案效率高且易于实施(和扩展)。