MongoDB:地图/单位建议在浏览器游戏中进行模型设计

时间:2011-07-08 21:28:49

标签: mysql ruby-on-rails-3 mongodb mongoid

我在2~3天前开始研究MongoDB,我感到非常高兴:) 但是..我确实有一些问题..我已经做了一些研究,但他们没有澄清太多......我正在开发一个浏览器游戏,所有数据库都在MySQL中,但我决定迁移到MongoDB。但是,好的,问题。

1)在 MySQL 中,我曾经有一个 map 表,其中包含字段* map_ndx *, terrain (terrain是对terrain表的外部引用)。基本上,每个* map_ndx *表示不同的地图,表示它们的坐标; terrain 表示像“树林”,“沙漠”,分类在另一张桌子上。现在,在 MongoDB 上,我有一个 map 集合,它有一个字段* map_ndx *,并嵌入了几个 tiles 。每个磁贴都包含字段 col row ,并嵌入 terrain 。首先,您认为这种设计对地图有效吗?例如,我会在搜索“地图z上的tile(x,y)”时进行大量查询。其次,我在哪里放置索引(例如)?我是否将它们放在 tile 集合中,或者放在 map 集合中(例如,使用“index”tile.row'“)?我问这个是因为在MySQL上查询“select * from map where map_ndx = 1 and row = 1”时,我会立即得到答案。在MongoDB上,如果我要求“Map.where(:map_ndx => 1).first.tiles.where(:row => 1)”,则需要几乎一秒的时间才能完成(例如: RoR,我使用的是 mongoid

2)在 MySQL 中,我曾经有一个* global_units *表,它可以描述几个单位,他们的攻击,防御,成本等。每个玩家都会有一个* user_units *,引用了* global_units *,并通知了玩家对此引用的* global_unit *的单位数量。现在,在 MongoDB 上,我考虑在用户集合中嵌入* user_units *,这似乎是理想的选择。但是,我应该保持* user_units *仅引用* global_units *,或者最好是* global_unit *也嵌入在每个玩家的* user_units *集合中?问题是我必须从其他地方的* global_units *访问单位,例如当玩家要构建它们时。因此,即使我将它们嵌入* user_units *集合中,我也需要一个独有的非嵌入式* global_units *集合,因此我可以在其他地方访问它们的信息。这里最好的方法是什么?

我知道这些都是非常具体的问题,但如果有人向我澄清这些问题,我会很高兴的! 提前致谢, 费尔南多。

1 个答案:

答案 0 :(得分:3)

您在这里提出的问题是复杂的“嵌入与参考”问题。第一个问题是这里没有单一的正确答案,这是一系列的权衡。有时最好引用,有时最好嵌入。

这里有一个答案详细one example

这里的一个重要基本问题围绕着“顶级”对象。这是我个人的经验法则:

  1. 如果某个对象仅在其父级的上下文有用,那么您通常会嵌入。
  2. 如果某个对象没有其父级,那么您通常会引用它。
  3. 问题#2 ,我想你在这里找到了答案:

    • user_units仅在user的上下文中有用。如果您要加载user,为什么不同时加载units
    • global_units在没有user_unit上下文的情况下很有用,因此您可能希望参考。当然你有一个单位的“全局查询”,但你有多少?几百?几千?它们都适合记忆吗?

    所以user会有类似

    的内容
    { _id: 'gates',
      units: { footman: 10, cannon: 3, horse: 5 }
    }
    

    这似乎很好,如果用户需要一个新的仆人,查看统计数据真的很麻烦吗?当然,如果你真的想要自定义,你可以在我的脚上存储统计数据,如果它们不同的话。

    问题#1 :有点儿干。

    mapstiles的确切关系如何?一个map是否包含许多tiles?您是否愿意在一个tiles中构建map的哈希表?

    这就是我所看到的:

    { _id: 'map1',
      name: 'jungle',
      height: 20,
      width: 20
      tiles: { "0_0": { type: 'jungle' },
               "0_1": { type: 'jungle' },
               ...
               "19_19": { type: 'beach' }
             }
    }
    

    注意我不是在构建一个tile数组,而是一个实际的hashtable。我将所有瓷砖填充到一个地图中并将整个内容加载到内存中。当然,这假设您想要地图上的所有图块。

    我知道您的查询仅查看一行,但现在问题是您需要多久一次?你一般不需要一块方形的瓷砖块吗?