我相信至少有两种方法可以在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'等).
如果您有这样的用例,通常首选使用第二种方法吗?
在第一种方法中,您无法索引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副总裁指出
db.your_collection.find({'lines.idk73716':{$exists:true}})
.如果要使用"ids as keys"版本,则存在的查询将起作用,但它不可转换
我们仍然可以使用$ exists来查询id,但它不能被索引