我应该如何在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步:实体

让我们从简单的开始: UserCampaign 。 这些确实是两个单独的对象,没有一个真正依赖于另一个对象的存在。 这两者之间也没有隐含的分歧:用户不属于活动,活动也不属于用户。

当你有两个这样的顶级对象时,他们通常会自己collections。 所以你需要一个Users集合和一个Camapaigns集合。

第2步:映射

UserCampaign目前用于表示一个N对M的映射。 现在,一般情况下,当你有一个N对1的映射时,你可以把N放在1的内部。但是,对于N到M映射,你通常必须“select一边”。

从理论上讲,您可以执行以下任一操作:

  1. 在每个User的内部放置一个Campaign ID列表
  2. 在每个Campaign放置一个Users ID列表

就我个人而言,我会做#1。 你可能有更多的用户使用这个广告系列,你可能想把数组放在更短的地方。

第3步:交易

点击确实是一个完全不同的野兽。 在对象方面,你可以想到以下几点: Clicks “属于” UserClicks “属于”一个Campaign 。 所以,从理论上讲,只要存储点击是这些对象的一部分即可。 很容易认为点击属于用户或广告系列。

但是,如果你真的深入了解,上面的简化实际上是有缺陷的。 在你的系统中, Clicks确实是一个中心对象。 实际上,您甚至可以说用户和广告系列实际上只是与点击相关联。

看看你问的问题。 所有这些问题都是以点击为中心的。 用户和广告系列不是数据中的核心对象,点击是。

此外,点击将成为您系统中最丰富的数据。 你将有更多的点击比其他任何方式。

devise这样的数据模式时,这是最大的困难。 有时候,如果不是最重要的东西,你需要推掉“父母”对象。 想象一下,build立一个简单的电子商务系统。 很明显, orders将“属于” users ,但是orders对于系统是如此重要,以至于它将成为“顶级”对象。

把它包起来

你可能会需要三个集合:

  1. 用户 – >有campaign._id列表
  2. 运动
  3. 点击 – >包含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}

  1. 如果某公司的某些内容发生更改,mongodb更新大量文档并不是问题。

  2. 有嵌套收集或没有真正取决于收集多less数据。 在你的情况下,如果你知道'点击'收集将包含'大量的数据',你需要创build一个单独的集合。 因为肯定的'点击',你将需要分页,过滤等,比用户将'光'集合。

所以我build议如下:

 User { Campaigns: [] } Clicks { user_id, camp_id }