【发布时间】:2012-01-28 09:32:07
【问题描述】:
我将 MongoDB + PHP 用于具有不同类型的提要(帖子、照片、投票等)和 cmets 的“facebookish”新闻提要。
每个供稿都属于某个“频道” - 当前可能是 user 或 group(将来可能会有更多容器)。
任何用户都可以订阅或取消订阅任何频道。
现在假设有大量的频道和大量的提要。通道/feeds/cmets 的最佳结构是什么?
我正在考虑两种方法:
1) Feed 集合,其中包含每个 Feed 中的订阅者列表:
feeds:
[
{date_added: ...,
last_update: ...,
title: ...,
text: ...,
channel: ...,
channel_subscribers: [...],
comments_subscribers: [...],
comments: [...]
},
{...},
{...},
{...}
]
如果我想获得最后的提要:
db.feeds.find({date_added: "this week", channel_subscribers: "my_login"});
如果我想获得新 cmets 的供稿:
db.feeds.find({last_update: "this week", comments_subscribers: "my_login"});
优点:
- 简单快速的读数?
缺点:
- 当我想订阅/取消订阅频道/取消订阅频道时,我必须运行 通过所有提要并从列表中推/拉我的名字 频道订阅者;如果我有大量的提要,它可能会很慢
2) 单独的“渠道”集合: 同样的事情,但在频道集合中保留订阅者列表:
channels:
[
{channel_id:..., last_update: ..., subscribers: [...]},
{channel_id:..., last_update: ..., subscribers: [...]}
]
首先我要查询最后更新的频道:
subscribes = db.channels.find({last_update: "today", subscribers: "my_login"})
现在找到我的供稿:
db.feeds.find({channel: {$in: subscribes}], date_added: "today"})
优点:
- 订阅/退订简单、快速、安全;
缺点:
- 我觉得我应该避免使用 $in,因为它很慢(?),尤其是当我有很多 订阅放在这个操作符里面。
3) 将用户订阅保存在 users 集合中(因此每个用户都有自己的订阅数组)
users:
[
{_id: ..., login: ..., email: ..., subscribes: [...]}
]
缺点: - 在这种情况下,我们将在 $in 中放入比之前(#2)方法更大的数组。
4) 您的建议?
【问题讨论】:
-
MongoDB 建议您使用的数据结构适合您最常见的用例。不过,理解您当前的结构仍然有些困难。你能详细说明一下你的结构吗?
-
好的,让我简化一下我的问题。什么会更快:保留我的订阅列表,然后将那个大数组放在“$in”运算符中,然后通过它获取我的提要;或者 - 通过我的登录名获取订阅源 - 当每个订阅源中都有大量(约 2000 个)订阅者时? (在这么大的数组上创建多键索引是一种好习惯吗?)
-
我认为将订阅者保留在订阅源本身是个坏主意。将它们链接起来可能会更好。这看起来有点 SQLey,但它也便于搜索和删除。
-
谢谢!我想我最好对这两种情况进行速度测试并在此处发布结果。
标签: php performance mongodb feed