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

时间:2011-01-11 20:53:44

标签: 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

我需要能够:

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

如果我按照

的方式做某事
User {
     Campaigns: [
         {
           Clicks: []
         }
     ]
}

我遇到两个问题:

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

3 个答案:

答案 0 :(得分:87)

好的,我认为你需要将其分解为基本的“变种”。

你有两个“实体”式对象:

  • User
  • Campaign

你有一个“映射”式对象:

  • UserCampaign

您有一个“交易”式对象:

  • Click

第1步:实体

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

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

第2步:制图

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

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

  1. Campaign ID
  2. 中添加User个列表
  3. Users ID
  4. 中添加Campaign个列表

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

    第3步:交易

    点击是一个完全不同的野兽。在对象术语中,您可以考虑以下事项:Clicks“属于”UserClicks“属于”Campaign。因此,理论上,您可以只存储点击是这些对象中的任何一个的一部分。很容易认为Clicks属于 用户或广告系列。

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

    查看您提出的问题/疑问。所有这些问题实际上都围绕着点击。 用户&广告系列不是数据中的中心对象,点击次数为。

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

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

    结束

    您可能需要三个系列:

    1. 用户 - >有campaign._id
    2. 列表
    3. 运动
    4. 点击次数 - >包含user._id,campaign._id
    5. 这应满足您的所有查询需求:

        

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

      db.clicks.find()
      
        

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

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

        

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

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

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

答案 1 :(得分:3)

我在这里看到的主要问题是您正在尝试将关系数据库概念应用于面向文档的数据库。两者之间的主要区别在于您不必担心NOSQL数据库中的模式或结构,而是担心集合和文档。

理解在SQL中的NOSQL的许多实现中没有连接概念是非常重要/必要的。这意味着如果您将数据分布在集合中,那么您需要做很多工作以便以后粘贴它。与SQL db的规范化一样,通过在集合中传播数据也没有其他收获。您需要考虑哪些数据是文档的一部分以及它适用于哪个集合,从不担心NOSQL db下的实现。所以对于你的问题,答案可能是......并且会支持你所要求的所有......

db.trackclicks ==>集合
trackclick = {           操作系统:XP,           用户:John Doe,           广告系列:{title:test,desc:test,link:url},           推荐人:google.com           }

答案 2 :(得分:2)

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

  2. 嵌套集合还是没有真正取决于集合中的数据量。 在您的情况下,如果您知道'点击'集合将包含'大量数据',您需要创建一个单独的集合。因为“点击”肯定会需要分页,过滤等,而且用户将是“轻量级”收藏。

  3. 所以我建议关注:

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