我相信至少有两种方法可以在mongodb文档中嵌入数据。在简化的情况下,我们可以这样:
{
'name' : 'bill',
'lines': {
'idk73716': {'name': 'Line A'},
'idk51232': {'name': 'Line B'},
'idk23321': {'name': 'Line C'}
}
}
并作为数组:
{
'name' : 'bill',
'lines': [
{'id': 'idk73716', 'name': 'Line A'},
{'id': 'idk51232', 'name': 'Line B'},
{'id': 'idk23321', 'name': 'Line C'}
]
}
正如您在此用例中所看到的,保持每一行的ID非常重要。
我想知道这两种模式之间是否存在利弊。特别是当涉及到使用索引时,我感觉第二个可能更容易使用,因为可以在'lines.id'或甚至'lines.name'上创建索引来搜索所有文档中的id或名称。在第一个例子中,我没有找到任何工作解决方案来索引id('idk73716'等)。
如果您有这样的用例,是否通常首选使用第二种方法?
答案 0 :(得分:10)
在第一种方法中,您无法索引id字段,因为id用作键。它的行为类似于键值字典。如果你有一组已知的id(当然数量较少),这种方法很有用。假设在你的第一个例子中,id在前面是众所周知的,
>>db.your_colleection.find()
{ "_id" : ObjectId("4ebbb6f974235464de49c3a5"), "name" : "bill",
"lines" : {
"idk73716" : { "name" : "Line A" },
"idk51232" : { "name" : "Line B" } ,
"idk23321": { "name" : "Line C" }
}
}
所以要查找id字段idk73716的值,可以通过
执行此操作 db.your_colleection.find({},{'lines.idk73716':1})
{ "_id" : ObjectId("4ebbb6f974235464de49c3a5"), "lines" : { "idk73716" : { "name" : "Line A" } } }
empty {}表示查询,第二部分{'lines.idk73716':1}是查询选择器。
将id作为键具有单独选择特定字段的优势。即使{'lines.idk73716':1}是字段选择器,此处它也可用作查询和选择器。但这不能在你的第二种方法中完成。假设第二个集合有点像这样
> db.second_collection.find()
{ "_id" : ObjectId("4ebbb9c174235464de49c3a6"), "name" : "bill", "lines" : [
{
"id" : "idk73716",
"name" : "Line A"
},
{
"id" : "idk51232",
"name" : "Line B"
},
{
"id" : "idk23321",
"name" : "Line C"
}
] }
>
您索引了字段ID,因此如果您想按ID
进行查询> db.second_collection.find({'lines.id' : 'idk73716' })
{ "_id" : ObjectId("4ebbb9c174235464de49c3a6"), "name" : "bill", "lines" : [
{
"id" : "idk73716",
"name" : "Line A"
},
{
"id" : "idk51232",
"name" : "Line B"
},
{
"id" : "idk23321",
"name" : "Line C"
}
] }
>
通过查看上面的输出,可以看出没有办法单独选择匹配的子(嵌入)文档,但是在第一种方法中是可能的。这是mongodb的默认行为。
见
db.second_collection.find({'lines.id' : 'idk73716' },{'lines':1})
将获取所有行,而不仅仅是idk73716
{ "_id" : ObjectId("4ebbb9c174235464de49c3a6"), "lines" : [
{
"id" : "idk73716",
"name" : "Line A"
},
{
"id" : "idk51232",
"name" : "Line B"
},
{
"id" : "idk23321",
"name" : "Line C"
}
] }
希望这有帮助
修改强>
感谢@Gates VP指出
db.your_collection.find({'lines.idk73716':{$exists:true}})
。如果你 想要使用“ids作为键”版本,存在的查询将起作用,但是 它不可索引
我们仍然可以使用$ exists来查询id,但它不会是可索引的
答案 1 :(得分:0)
今天我们有$ eleMatch运算符来实现这一点,正如这里所讨论的那样 - Retrieve only the queried element in an object array in MongoDB collection
但是这个问题提出了一些有趣的设计选择,我今天也在努力做出这些选择。 如果在嵌入式文档中需要频繁的CRUD,那么从给定的两个选项中选择什么应该是什么?
我发现,当ID用作属性名称时,在嵌入式文档中使用新的$ set / $ unset运算符执行CRUD很容易。如果客户端可以获取ID进行编辑,那么它比阵列,IMO更好。 这是Mongodb关于模式设计和做出这些设计决策的另一个有用的博客
http://blog.mongodb.org/post/87200945828/6-rules-of-thumb-for-mongodb-schema-design-part-1