我应该如何在MongoDB中实现这个模式?
我正在尝试编写一个跟踪脚本,并且在确定数据库应该如何工作时遇到了麻烦。
在MySQL中,我会创build一个类似于的表
User: username_name: string Campaign: title: string description: string link: string UserCampaign: user_id: integer camp_id: integer Click: os: text referer: text camp_id: integer user_id: integer
我需要能够:
- 查看来自IP,Referer,OS等每个点击的信息
- 查看X IP,X Referer,X OS的点击次数
- 将每次点击与用户和广告系列相关联
如果我按照…的方式做一些事情
User { Campaigns: [ { Clicks: [] } ] }
我碰到两个问题:
- 它为每个用户创build一个新的活动对象,这是一个问题,因为如果我需要更新我的广告系列,我需要更新每个用户的对象
- 我期望Clicks数组包含大量的数据,我觉得让它成为User对象的一部分会使查询非常慢
好的,我认为你需要把这个分解成基本的“品种”。
你有两个“实体”风格的对象:
-
User
-
Campaign
你有一个“映射”风格的对象:
-
UserCampaign
你有一个“事务性”风格的对象:
-
Click
第1步:实体
让我们从简单的开始: User
和Campaign
。 这些确实是两个单独的对象,没有一个真正依赖于另一个对象的存在。 这两者之间也没有隐含的分歧:用户不属于活动,活动也不属于用户。
当你有两个这样的顶级对象时,他们通常会自己collections。 所以你需要一个Users
集合和一个Camapaigns
集合。
第2步:映射
UserCampaign
目前用于表示一个N对M的映射。 现在,一般情况下,当你有一个N对1的映射时,你可以把N放在1的内部。但是,对于N到M映射,你通常必须“select一边”。
从理论上讲,您可以执行以下任一操作:
- 在每个
User
的内部放置一个Campaign ID
列表 - 在每个
Campaign
放置一个Users ID
列表
就我个人而言,我会做#1。 你可能有更多的用户使用这个广告系列,你可能想把数组放在更短的地方。
第3步:交易
点击确实是一个完全不同的野兽。 在对象方面,你可以想到以下几点: Clicks
“属于” User
, Clicks
“属于”一个Campaign
。 所以,从理论上讲,只要存储点击是这些对象的一部分即可。 很容易认为点击属于用户或广告系列。
但是,如果你真的深入了解,上面的简化实际上是有缺陷的。 在你的系统中, Clicks
确实是一个中心对象。 实际上,您甚至可以说用户和广告系列实际上只是与点击相关联。
看看你问的问题。 所有这些问题都是以点击为中心的。 用户和广告系列不是数据中的核心对象,点击是。
此外,点击将成为您系统中最丰富的数据。 你将有更多的点击比其他任何方式。
devise这样的数据模式时,这是最大的困难。 有时候,如果不是最重要的东西,你需要推掉“父母”对象。 想象一下,build立一个简单的电子商务系统。 很明显, orders
将“属于” users
,但是orders
对于系统是如此重要,以至于它将成为“顶级”对象。
把它包起来
你可能会需要三个集合:
- 用户 – >有campaign._id列表
- 运动
- 点击 – >包含user._id,campaign._id
这应该满足您的所有查询需求:
查看来自IP,Referer,OS等每个点击的信息
db.clicks.find()
查看X IP,X Referer,X OS的点击次数
db.clicks.group()
或运行Map-Reduce 。
将每次点击与用户和广告系列相关联
db.clicks.find({user_id : blah})
也可以将点击标识推送到用户和广告系列(如果有意义的话)。
请注意,如果您有大量的点击次数,您将不得不分析您最常用的查询。 您无法在每个字段上编制索引,因此您经常需要运行Map-Reduces来“汇总”这些查询的数据。
我在这里看到的主要问题是,您正试图将关系数据库的概念应用于面向文档的数据库。 两者之间的主要区别在于,您不必担心NOSQL数据库中的模式或结构,而是关于收集和文档。
理解在SQL的许多NOSQL实现中没有连接的概念是非常重要/必要的。 这意味着如果您将数据分布在集合中,那么稍后您将完成大量工作。 另外,通过在SQL数据库的规范化过程中将数据分布到集合中也没有其他的好处。 你需要考虑哪些数据是你的文档的一部分,以及它适用于哪个集合,而不用担心NOSQL数据库下的实现。 所以对于你的问题,答案可能是..并将支持你所要求的…
db.trackclicks ==>集合
trackclick = {OS:XP,用户:John Doe,Campaign:{title:test,desc:test,link:url},Referrer:google.com}
-
如果某公司的某些内容发生更改,mongodb更新大量文档并不是问题。
-
有嵌套收集或没有真正取决于收集多less数据。 在你的情况下,如果你知道'点击'收集将包含'大量的数据',你需要创build一个单独的集合。 因为肯定的'点击',你将需要分页,过滤等,比用户将'光'集合。
所以我build议如下:
User { Campaigns: [] } Clicks { user_id, camp_id }