我应该如何在MongoDB中实现这个模式?

Chr*_*ini 27 database-design mongodb

我正在尝试编写一个跟踪脚本,但我无法弄清楚数据库应该如何工作.

在MySQL中,我创建了一个类似于的表

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
Run Code Online (Sandbox Code Playgroud)

我需要能够:

  • 查看每次点击的信息,如IP,Referer,OS等
  • 查看来自X IP,X Referer,X OS的经常点击次数
  • 将每次点击与用户和广告系列相关联

如果我按照自己的方式做点什么的话

User {
     Campaigns: [
         {
           Clicks: []
         }
     ]
}
Run Code Online (Sandbox Code Playgroud)

我遇到两个问题:

  • 它会为每个用户创建一个新的广告系列对象,这是一个问题,因为如果我需要更新我的广告系列,我需要更新每个用户的对象
  • 我希望Clicks数组包含大量数据,我觉得让它成为User对象的一部分会使查询速度变慢

Gat*_* VP 88

好吧,我认为你需要将其分解为基本的"变种".

你有两个"实体"式对象:

  • User
  • Campaign

你有一个"映射"式对象:

  • UserCampaign

你有一个"事务性"风格的对象:

  • Click

第1步:实体

让我们从简单的开始:User&Campaign.这些是真正的两个独立的对象,它们的存在都不会真正依赖于另一个.两者之间也没有隐含的层次结构:用户不属于"广告系列","广告系列"也不属于"用户".

当你有两个像这样的顶级对象时,他们通常会获得自己的收藏.所以你需要一个Users集合和一个Camapaigns集合.

第2步:映射

UserCampaign目前用于表示N对M映射.现在,一般来说,当你有一个N对1的映射时,你可以将N放在1中.但是,通过N对M映射,你通常必须"选择一个边".

理论上,您可以执行以下操作之一:

  1. 列出Campaign ID每个内部的s 列表User
  2. 列出Users ID每个内部的s 列表Campaign

就个人而言,我会做#1.您可能有更多用户参与广告系列,您可能希望将数组放在更短的位置.

第3步:交易

点击是一个完全不同的野兽.在对象术语中,您可以考虑以下内容:Clicks"属于"a User,Clicks"属于"a Campaign.因此,理论上,您可以只存储点击是这些对象中的任何一个的一部分.人们很容易认为,点击所属下的用户或广告活动.

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

看看你问的问题/疑问.所有这些问题实际上都围绕着点击.用户和广告系列不是数据中的中心对象,点按即可.

此外,Clicks将成为您系统中最丰富的数据.您将获得比其他任何内容更多的点击次数.

这是为这样的数据设计模式时最大的障碍.有时,当它们不是最重要的东西时,你需要推掉"父"对象.想象一下构建一个简单的电子商务系统.很明显,orders它将"属于" users,但orders它对系统至关重要,它将成为一个"顶级"对象.

把它包起来

你可能想要三个集合:

  1. 用户 - >包含campaign._id列表
  2. 运动
  3. 点击次数 - >包含user._id,campaign._id

这应该满足您的所有查询需求:

查看每次点击的信息,如IP,Referer,OS等

db.clicks.find()
Run Code Online (Sandbox Code Playgroud)

查看来自X IP,X Referer,X OS的经常点击次数

db.clicks.group()或运行Map-Reduce.

将每次点击与用户和广告系列相关联

db.clicks.find({user_id : blah}) 也可以将点击ID推送到用户和广告系列中(如果有意义的话).

请注意,如果您有大量的点击次数,那么您真的必须分析您最常运行的查询.您无法在每个字段上编制索引,因此您通常需要运行Map-Reduces来"汇总"这些查询的数据.

  • 我只是想说3年后,我仍然每隔一段时间回到这个答案,以保持这些概念在我的头脑中.再次感谢您的回答! (3认同)
  • 谢谢你的回答!这真的帮助我理解了在设计模式时我应该考虑什么 (2认同)