我在MongoDB的集合x
上有这样的文档:
{
"_id" : ...
"attrKeys": [ "A1", "A2" ],
"attrs" : {
"A1" : {
"type" : "T1",
"value" : "13"
},
"A2" : {
"type" : "T2",
"value" : "14"
}
}
}
上面的A1
和A2
元素只是示例:attrs
字段可以包含任意数量的任意名称的键。 attrs
中的密钥名称存储在attrNames
字段中。
我想查询具有attr
且具有给定值的子字段的文档。例如,对attr
键映射中具有子字段type
的元素的文档的查询是" T4"。像这样:
db.x.find({"attrs.$any.type": "T4"})
(avobe不是合法的MongoDB查询语言,但我认为它有助于理解这一点。)
MongoDB可以进行查询吗?在MongoDB不支持该查询的情况下是否有任何解决方法?谢谢!
编辑:数据模型的原始版本使用attrs
的数组而不是键映射。但是,为了允许在同一文档上进行并发修改,这改变了有利于键映射。
我的意思是,使用键映射两个独立的客户端可以修改attrs
元素,因为一个客户端可以db.x.update({_id: "y"}, {$set: { "attrs.A1.value": "12" } }
而另一个客户端db.x.update({_id: "y"}, {$set: { "attrs.A2.value": "55" } }
可以互相干扰。
在使用数组的情况下,并发访问要困难得多。有关如何做到的任何提示吗?
答案 0 :(得分:1)
MongoDB始终可以实现这一点,因为始终能够使用JavaScript evaluation构建查询条件:
db.attrs.find(function() {
var attrs = this.attrs;
return Object.keys(attrs).some(function(key) {
return attrs[key].value === "14"
});
})
通过在文档中搜索所需值的可能键,它将正确返回与此条件匹配的文档。
但这不是一个关于“可能”的问题,但是“更多的是这个真的好主意”,其基本答案是“不”。
数据库是变幻无常的野兽,喜欢用索引之类的东西进行优化,以及他们自己期望的运算符集,以使搜索尽可能高效地使用。所以,是的,您可以通过一个语言解释器,有效的暴力评估每个文档的编码条件,或者您可以重新考虑您的设计模式。
数据库喜欢“订单”,所以给它一些,因为你建议的数据有一个简单有组织的重组:
{
"attrs" : [
{ "key": "A1", "type" : "T1", "value" : "13" },
{ "key": "A2", "type" : "T2", "value" : "14" }
]
}
以这种方式组织查询变得如此简单:
db.attrs.find({ "attrs.value": "14" })
当然可以在数组子文档的任何属性上支持和使用索引。
MongoDB毕竟是一个“数据库”,并且像所有数据库一样,它最关心的是它的属性的“值”,而不是使用它的“密钥”的名称进行搜索。所以代表有意义的“数据”的东西不应该是“关键”名称的一部分,而应该是“关键”作为“标识符”的“价值”,如上所示。
使用您希望查询的数据的一致路径是在MongoDB中处理数据的最佳方式。使用密钥名称正在发生变化的结构,除了运行代码之外的其他任何东西都不能遍历,并且这么慢,而且性能比使用索引等本机操作和设施更差。