我在Mongo文档中找到有关处理嵌入式文档的任何有用的东西都很麻烦。假设我有以下架构:
{
_id: ObjectId,
...
data: [
{
_childId: ObjectId // let's use custom name so we can distinguish them
...
}
]
}
删除data
内所有内容的最有效方法是什么?
特别_id
?
删除嵌入式文档的最有效方法是什么?
特定_childId
在给定的_id
内?什么是表现
在这里,可以_childId
进行索引以实现对数(或
类似的)复杂性而不是线性查找?如果是这样,怎么样?
插入大量的最有效方法是什么(比方说1000)
对于给定的data
,文档到_id
?如上所述,我们可以得到
O(n log n)或类似的复杂性与正确的索引?
对于给定的data
,获取_id
内的文档数量的最有效方法是什么?
答案 0 :(得分:4)
另外两个答案为您的问题1-4提供了明智的建议,但我想通过质疑首先询问它的基础来解决您的问题。存储“文档”的MongoDB环境中的“嵌入式文档”术语使人们感到困惑。您不应该将嵌入式文档视为MongoDB中的另一个文档,您将其作为自己的文档进行搜索,索引或更新,因为它不是它的本质。它是文档中的分组字段集合;它是type Object的BSON字段。引用embedded document docs,
嵌入式数据模型允许应用程序在相同的数据库记录中存储相关的信息。因此,应用程序可能需要发出更少的查询和更新以完成常见操作。
从有关您的用例的知识开始,您应该选择您的文档和文档结构,以使您的常见操作更容易。如果您非常关注1-4,您可能希望将data
childId
数组展开到单独的文档中。这个常见的“反模式”的一个具体示例是一个包含许多作者的博客 - 您可以拥有一个用户文档,其中嵌入了大量不断变化的帖子,或者一个帖子文档,其中每个都复制了用户信息。我不能确定您的数据模型有什么问题或没有错,因为您没有提供有关它的具体细节,但很难理解为什么1-4看起来很难或没有文档或MongoDB中的速度慢是一个好的迹象你应该重新考虑数据模型,所以相当于1-4是有趣和容易的!或者至少更容易和更有趣。
答案 1 :(得分:3)
我找不到速度上的任何内容,所以我会采用文档中的方法,希望他们能够以最有效的方式记录下来:
如果您要删除数据中的所有子文档,只需将data
更新为[]
从数据中移除包含特定_childId
的文档的官方方法是$pull:
db.collection.update(
{ },
{ $pull: { data: { _childId: id } } },
)
如果{ multi: true }
不唯一(多部分子文档),可能需要添加_childId
在对子文档进行索引时,我会将您引用到this question。简短回答是的,您可以索引子文档中的字段以便更快地查找,就像您通过
索引普通字段一样db.collection.ensureIndex({"data._childId" : 1})
如果只想在一个特定文档中搜索子文档,可以使用aggregation,即
db.collection.aggregate({$match:{_id : _id},
{$unwind:'$data'},
{$match:{data._childId: _childID})
首先匹配_id,然后才匹配_childId
。它将返回包含仅包含_childId
子文档的数据的父文档。
虽然有1000个子文档,但你可能不希望在一个查询中执行此操作$push
答案 2 :(得分:1)
db.collection.update({_id:yourId},{$set:{data:[]}})
_id
是唯一的,因此使用db.collection.findOne({_id:yourId},{"data._childId":1,_id:0}).data.length
或使用它等同于更有意义作为选择驱动程序中的原始命令。由于连接已经建立,除非数组非常大,否则简单地返回数据而不是在可能(过度)加载的服务器上完成计算应该更快。根据你对Trudberts的评论回答:_id
是独一无二的。因此,对于已知的_id,只需要修改一个文档:db.collection.update({_id:theId},{$pull....
。它没有提高效率。对于未知的id,在childId上创建一个索引,并使用childId而不是id执行相同的pull操作,并将multi选项设置为删除对特定childId的所有引用。
我强烈反对Trudberts建议使用聚合框架在需要时从优化数据中创建文档。目前,我有一个聚合管道,可以在6秒内分析5M记录,相互之间的关系超过700万。在非分片独立实例上。旋转磁盘,蹩脚的IO,甚至没有优化。通过仔细规划聚合(早期匹配限制传递给目前未处理的文档的文档)并将它们与早期结果合并(在组阶段中调整_id可以实现这一点),您甚至可以将其优化为仅仅几分之一秒,如果绝对必要的话。