【问题标题】:CouchDB Mango query - Match any key with array itemCouchDB Mango 查询 - 将任何键与数组项匹配
【发布时间】:2021-03-23 00:16:17
【问题描述】:

我有以下文件:

{
  "_id": "doc1"
  "binds": {
    "subject": {
      "Test1": ["something"]
    },
    "object": {
      "Test2": ["something"]
    }
  },
},
{
  "_id": "doc2"
  "binds": {
    "subject": {
      "Test1": ["something"]
    },
    "object": {
      "Test3": ["something"]
    }
  },
}

我需要一个 Mango 选择器来检索文档,其中绑定的任何字段(主题、对象等)都有一个对象,其键等于作为参数传递的数组中的任何值。即if keys of binds contains any values of some array it should returns that document

例如,考虑数组["Test2"],我的选择器应该检索doc1,因为binds["subject"]["Test1"] 存在;数组["Test1"] 应该检索doc1doc2,数组["Test2", "Test3"] 也应该检索doc1doc2

仅供参考。我正在使用带有nano lib 的 Node.js 来访问 CouchDB API。

【问题讨论】:

  • 我解决了更改表示的问题。但是,我会保留这个问题,以防有人在不改变这个原始表示的情况下找到解决方案。

标签: node.js couchdb couchdb-nano couchdb-mango


【解决方案1】:

我提供这个答案是因为改变文档“模式”并不总是一种选择。

对于给定的文档结构,这无法通过 Mango 以任何合理的方式完成。是的,它可以完成,但只有在采用非常脆弱和低效的做法时。

Mango 没有提供查询文档以获取动态属性的有效方法;它确实支持在属性值中搜索,例如数组1.

使用最坏的做法,此选择器将找到具有绑定属性 subjectobject 的文档具有名为 Test2Test3 的属性

{
   "selector": {
      "$or": [
         {
            "binds.subject.Test2": {
               "$exists": true
            }
         },
         {
            "binds.object.Test2": {
               "$exists": true
            }
         },
         {
            "binds.subject.Test3": {
               "$exists": true
            }
         },
         {
            "binds.object.Test3": {
               "$exists": true
            }
         }
      ]
   }
}

Yuk

问题

  1. 查询的属性名称不同,因此无法利用 Mango 索引(Test37 有人吗?)
  2. 因为 (1) 每次查询都会发生一次全索引扫描 (_all_docs)
  3. 需要以编程方式生成$or 子句
  4. 需要了解要查询的属性名称集(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 例如需要内存扫描,这可能非常昂贵。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-17
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    相关资源
    最近更新 更多