我在跟踪这个医生
http://docs.doctrine-project.org/projects/doctrine-mongodb-odm/en/latest/tutorials/getting-started.html
及
http://symfony.com/doc/current/bundles/DoctrineMongoDBBundle/index.html
当我保存文档时,我有两个集合
这样地:
{
"_id" : ObjectId("5458e370d16fb63f250041a7"),
"name" : "A Foo Bar",
"price" : 19.99,
"posts" : [
{
"$ref" : "Embedd",
"$id" : ObjectId("5458e370d16fb63f250041a8"),
"$db" : "test_database"
}
]
}
我想要
{
"_id" : ObjectId("5458e370d16fb63f250041a7"),
"name" : "A Foo Bar",
"price" : 19.99,
"posts" : [
{
"mycomment" :"dsdsds"
" date" : date
}
]
}
我想把我的数据非标准化。我该怎么做?
我可以使用MongoDB的$push、$addtoset等方法吗?
谢谢
最佳答案
条令odm支持references和embedded documents。
在第一个例子中,您使用的是引用。主文档(假设它被称为产品)引用了许多post文档。那些post文档位于它们自己的集合中(出于某种原因,这被命名为Embedd
——如果您保留此架构,我建议重命名它)。默认情况下,odm对引用使用DBRef约定,因此每个引用本身就是一个带有$ref
、$id
和$db
字段的小型嵌入文档。
非规范化可以通过使用嵌入文档来实现(在您的案例中是@EmbedMany
映射)。如果要嵌入post文档,post类应映射为@EmbeddedDocument
。这告诉odm它不是一类文档(属于它自己的集合),因此它不必担心通过_id
等来跟踪它(事实上,嵌入的文档甚至不需要标识符,除非您想映射一个)。
我决定嵌入或引用的经验法则通常是问自己,“我是否需要父文档上下文之外的此文档?”如果一个帖子没有产品记录之外的标识,我很乐意将其嵌入;但是,如果我后来发现我的应用程序还想向用户显示其所有帖子的列表,或者我需要按帖子进行查询(例如,不考虑产品的所有最近帖子的提要),则我可以希望引用posts集合中的文档(或者根据需要复制嵌入的posts)。
或者,您可以决定帖子应该同时存在于它们自己的集合中并嵌入到产品中。在这种情况下,您可以创建一个abstractpost类作为@MappedSuperclass
并在那里定义公共字段。然后,使用post和embeddedpost子类(相应地映射)扩展它。您将负责创建一些代码来从post文档生成embeddedpost,这将适合嵌入Product.posts
数组。此外,您还需要处理顶级帖子和嵌入帖子之间的数据同步(例如,如果有人编辑了帖子评论,您可能还希望更新所有相应的嵌入版本)。
关于引用的主题:odm还支持引用映射的simple
选项,在这种情况下,它将只存储被引用文档的_id
而不是更大的dbref对象。在大多数情况下,让dbref存储每个被引用文档的集合和数据库名称是相当多余的;但是,如果您使用single-collection inheritance,dbref实际上是很有用的,因为odm使用对象来存储额外的鉴别器信息(即被引用对象的类)。