我提供这个答案是因为改变文档“模式”并不总是一种选择。
对于给定的文档结构,这无法通过 Mango 以任何合理的方式完成。是的,它可以完成,但只有在采用非常脆弱和低效的做法时。
Mango 没有提供查询文档以获取动态属性的有效方法;它确实支持在属性值中搜索,例如数组1.
使用最坏的做法,此选择器将找到具有绑定属性 subject 和 object 的文档具有名为 Test2 和 Test3 的属性
{
"selector": {
"$or": [
{
"binds.subject.Test2": {
"$exists": true
}
},
{
"binds.object.Test2": {
"$exists": true
}
},
{
"binds.subject.Test3": {
"$exists": true
}
},
{
"binds.object.Test3": {
"$exists": true
}
}
]
}
}
Yuk。
问题
- 查询的属性名称不同,因此无法利用 Mango 索引(Test37 有人吗?)
- 因为 (1) 每次查询都会发生一次全索引扫描 (
_all_docs)
- 需要以编程方式生成
$or 子句
- 需要了解要查询的属性名称集(Test37 有人吗?)
给定的文档结构是 Mango 索引和查询的显示停止器。
这就是 map/reduce 的亮点
考虑一个带有地图功能的view
function (doc) {
for(var prop in doc.binds) {
if(doc.binds.hasOwnProperty(prop)) {
// prop = subject, object, foo, bar, etc
var obj = doc.binds[prop];
for(var objProp in obj) {
if(obj.hasOwnProperty(objProp)) {
// objProp = Test1, Test2, Test37, Fubar, etc
emit(objProp,prop)
}
}
}
}
}
因此,map 函数为任何具有 binds 属性和两个嵌套属性的文档创建视图,例如binds.subject.Test1, binds.foo.bar.
鉴于问题中的两个文档,这将是基本视图索引
| id |
key |
value |
| doc1 |
Test1 |
subject |
| doc2 |
Test1 |
subject |
| doc1 |
Test2 |
object |
| doc2 |
Test3 |
object |
由于视图查询提供keys 参数,此查询将使用 JSON 提供您的特定解决方案
{
include_docs: true,
reduce: false,
keys: ["Test2","Test3"]
}
使用 cUrl 查询该索引
$ curl -G http://{查看端点} -d 'include_docs=false' -d
'reduce=false' -d 'keys=["Test2","Test3"]'
会回来
{
"total_rows": 4,
"offset": 2,
"rows": [
{
"id": "doc1",
"key": "Test2",
"value": "object"
},
{
"id": "doc2",
"key": "Test3",
"value": "object"
}
]
}
当然,有一些选项可以通过利用collation and complex keys 来扩展这种视图的形式和功能,还有方便的reduce 功能。
我看过评论说 Mango 非常适合 CouchDB 的新手,因为它在创建索引和查询选项方面“轻松”,如果更老练的话,它还可以映射/减少。我相信这样的 cmets 是善意的,但被误导了;芒果很诱人,但也有缺陷1。视图确实需要深思熟虑,但是,嘿,无论如何我们都应该这样做。
1)$elemMatch 例如需要内存扫描,这可能非常昂贵。