从未直接存储的MongoDB子文档应该是文档还是普通PHP类


Should a MongoDB SubDocument that's never stored directly be a Document or a plain PHP class?

我正在创建一个游戏,用户可以在其中设计自己的关卡(放置怪物,陷阱,任务等( 我正在使用Symfony 2.3,并选择MongoDB是因为它有Doctrine支持。

当有人编辑关卡并保存更改时,ZoneData JSON 将提交到服务器。 这个JSON的结构是一些参数(名称,大小,天气(和数百个ZoneObjects(大约有30种不同的类型(。 这些 ZoneObjects 中的每一个都是基类的扩展,例如......

class ZoneObject extends Document {
    protected $xPos;
    protected $yPos;
}
class MonsterObject extends ZoneObject {
    protected $name;
    protected $challengeRating;
}

这些区域对象现在只是文档,因为我知道它们不是实体。 我不确定它们应该是文档还是简单的普通类。 它们永远不需要自己保存,它们始终是ZoneData的一部分。 但是,它们确实需要验证,并通过表单进行编辑。

所以我的问题是 - 在这样的设置中,你会制作这些文档,还是坚持使用普通的旧 PHP 对象? 我担心一个嵌入了500个子文档的MongoDB文档将如何扩展。

如果我在这里错过了一些简单的东西,请道歉。

提前感谢,詹姆斯

MongoDB在插入时非常快,它的NoSQL性质意味着您将能够使用需要存储的尽可能多的信息来扩展文档。技术堆栈确保你可以写得非常快,但参考信息可能更难,我认为这对于游戏运行时更为重要。如果我正在设计一个关卡,我希望初始设置会占用更多的处理,但要让关卡本身渲染得非常快。

我会将您的 *对象设置为实体,并根据它们的类型将它们存储在不同的集合中。怪物会进入"怪物"收藏,"天气"会进入自己的收藏,等等。这背后的原因是集合存储具有类似范围的文档(这在您呈现的设计中是绝对正确的,尽管控制较少,请阅读下文(。

然后,我将拥有一个"区域"实体,该实体具有天气,怪物,环境等属性,并链接到每个特定集合中的条目。这里的优点是它更加分散,并且您可以更好地控制组件的范围。

最后,我将介绍一个 Level 实体,它引用与其关联的区域实体。

上述设置允许您根据需要轻松引用信息,并可以生成特定区域的报告等。它还具有所有内容都更容易测试的优点,您可以根据需要轮询信息。假设您有一张地图,当玩家进入关卡时会显示该地图。您可能希望显示天气或环境信息,但您不必检索该段的所有其他信息。当一个动作发生在一个区域中时,你会显示该区域的适当信息,但考虑到你更好的范围,你仍然可以控制你期望的每个元素(即你知道你只有一个关于天气的文档,但一个或多个关于怪物的文档(。

通过将事物构建为实体,您还可以访问Symfony出色的验证服务,该服务确实消除了您在构建表单和执行约束时通常面临的许多问题。

最后,请记住,

过早优化是魔鬼,这始终是公平的。有很多方法可以在不重组应用程序(缓存、Gearman 等(的情况下提高访问速度,您应该考虑最重要的事情是什么 - 为 alpha 版本构建和运行一些东西,或者提供应该完美无缺的付费服务。

我希望我已经涵盖了您的大部分担忧,但如果没有,请务必发表评论,我会更新我的答案!