我提供这个答案是因为改变文档“模式”并不总是一种选择。
对于给定的文档结构,这不能以任何合理的方式使用 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
}
}
]
}
}
玉。
问题
- 查询的属性名称不同,因此无法利用 Mango 索引(Test37 有人吗?)
- 因为 (1)每次查询都会发生一次全索引扫描( )
_all_docs
- 需要以编程方式生成
$or
子句
- 需要了解要查询的属性名称集(Test37 有人吗?)
给定的文档结构是 Mango 索引和查询的显示停止器。
这就是 map/reduce 的亮点
考虑一个带有地图功能的视图
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)
}
}
}
}
}
binds
因此,map 函数为具有两个嵌套属性的属性的任何文档创建一个视图binds.subject.Test1
,例如binds.foo.bar
.
鉴于问题中的两个文档,这将是基本视图索引
ID |
钥匙 |
价值 |
文档1 |
测试1 |
主题 |
文档2 |
测试1 |
主题 |
文档1 |
测试2 |
目的 |
文档2 |
测试3 |
目的 |
由于视图查询提供了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"
}
]
}
当然,还有一些选项可以通过利用排序规则和复杂的键来扩展这种视图的形式和功能,并且还有方便的reduce功能。
我看过评论说 Mango 非常适合 CouchDB 的新手,因为它在创建索引和查询选项方面“轻松”,如果对于经验更丰富的人来说,它的 map/reduce 也是如此。我相信这样的评论是善意的,但却被误导了;芒果很诱人,但也有缺陷1。视图确实需要相当多的思考,但是,嘿,无论如何我们都应该这样做。
1) $elemMatch
例如需要内存扫描,这可能非常昂贵。