SELECT ALL的CouchDB版本,其中field1 = value1,field2 = value2

时间:2017-03-13 16:32:50

标签: node.js couchdb

我有一个小型CouchDB表,其中包含以下文档结构:

{
    "_id": "22e5cfffa3d363bb1dd3f2293e002953",
    "idRubric": "9bf94452c27908f241ab559d2a0d46c5",
    "category": "open",
    "yada yada" : "for the rest of the fields"
 }

类别和(当前)有4种可能的idRubric值。我正在尝试创建一个视图,它允许我只选择idRubric和category同时匹配给定值的那些文档。我当前的地图功能如下所示:

{
   "_id": "_design/views",
   "_rev": "40-97b9c83b8016e4f71738bb64cbe6c754",
   "views": {
       "byRubricCategory": {
           "map": "function (doc) { if (doc.idRubric && doc.category) {emit(doc.idRubric, doc.category); } }"
       }
   }
}

这是一个数组,显示所有匹配ieRubric的文档。如果我将idRubric替换为类别,那么我将获得与该类别匹配的所有文档。我试图将结果指定为[doc.idRubric, doc.category],但是只返回一个空集。 根据建议,我已更新视图文档以输出数组:

{
   "_id": "_design/views",
   "views": {
       "byRubricCategory": {
           "map": "function (doc) { if (doc.idRubric && doc.category) {emit([doc.idRubric, doc.category], null); } }"
       }
   }
}

将emit更改为数组的结果是我现在得到一个空集:

{
  "total_rows": 16,
  "offset": 0,
  "rows": [

  ]
}

我没有使用reduce函数,因为(我的理解有限)map的目标似乎是将set减少为单个值,我不想要,我需要的结果集将在最小,有4个文件,可能有20-30。

我已经完成了关于CouchDB和这个主题的20个或主题,但所有似乎都引用了多个关键查询,其中焦点是key1或key2。我正在尝试使用逻辑AND而不是逻辑OR。谢谢。

未指定密钥时的代表值:

{
  "total_rows": 16,
  "offset": 0,
  "rows": [
    {
      "id": "22e5cfffa3d363bb1dd3f2293e00380a",
      "key": [
        "9bf94452c27908f241ab559d2a0d46c5",
        "close"
      ],
      "value": null
    },
    {
      "id": "22e5cfffa3d363bb1dd3f2293e0045a7",
      "key": [
        "9bf94452c27908f241ab559d2a0d46c5",
        "content"
      ],
      "value": null
    },
    {
      "id": "22e5cfffa3d363bb1dd3f2293e002953",
      "key": [
        "9bf94452c27908f241ab559d2a0d46c5",
        "open"
      ],
      "value": null
    },
    {
      "id": "22e5cfffa3d363bb1dd3f2293e0088a4",
      "key": [
        "9bf94452c27908f241ab559d2a0d50d6",
        "rising"
      ],
      "value": null
    }
  ]
}

3 个答案:

答案 0 :(得分:3)

实现这一目标的最简单方法是使用这样的地图函数:

function (doc) {
  if (doc.idRubric && doc.category) {
    emit([doc.idRubric, doc.category], null);
  }
}

然后,您必须使用startkey和endkey查找文档。

startkey = ["a", "b"]
endkey = ["a", "b", {}]

请记住,键应该是json字符串。 " {}"在endkey中意味着任何其他对象。它将匹配任何idRubric等于" a"和类别等于" b"。

另请注意,我不会随着密钥一起发出文档。如果您确实想要获取文档,除非您将发出的值传递给地图缩小,否则没有真正的理由发出文档。问题是您可以使用分配给发射值的文档来获取视图。所以你不必真正发出价值。这也会使视图变小。想象一下,你有一些文档内容有10mb的文档。如果你发出整个文档100次,你的文档实际上会浪费10mb x 100次= 1000mb的内存。

此外,您可能希望添加"类型"而不是idRubric和类别测试。到您的文档,使其更明确您的对象是什么。

你也可以使用它:

http://localhost:5984/rubric_content/_design/views/_view/byRubricCategory?startkey=[%229bf94452c27908f241ab559d2a0d46c5%22,%22content%22]&endkey=[%229bf94452c27908f241ab559d2a0d46c5%22,%22content%22,{}]

而不是使用" key"。当你有一组发射多个东西时很好。同样由于某种原因,您发出值的顺序也很重要。它将改变结果集的顺序。

我的方法优于"键"是你可以取这样的东西:

key: ["apple","orange"]
key: ["apple","orange"]
key: ["apple","orange","cherry"]
key: ["apple","lemon"]

使用"key" = ["apple","cherry"]的查询将返回前2个键。使用startkey=["apple","orange"]和带有["apple","orange",{}]的结束键的查询将返回前3个文档,因为所有这些文档都以apple和orange开头。考虑到这一点,如果您的startkeyendkey相同,则会像" key"。它只是指定两个键允许您编写更复杂的键范围。

还有一件事,如果您想要获取文档,请将"include_docs=true"添加到您的网址。

答案 1 :(得分:1)

好吧!答案是key=而非keys= 我一直在浏览器中测试这个: http://localhost:5984/rubric_content/_design/views/_view/byRubricCategory?keys=[%229bf94452c27908f241ab559d2a0d46c5%22,%22content%22]

错误是关键规范。将此更正为: http://localhost:5984/rubric_content/_design/views/_view/byRubricCategory?key=[%229bf94452c27908f241ab559d2a0d46c5%22,%22content%22]解决了这个问题。谢谢大家的帮助和耐心。

答案 2 :(得分:0)

emit ting [doc.idRubric, doc.category]因为您的密钥 是正确的方法。使用该复合键和您的查看文档,您应该可以执行以下操作:curl host:5984/dbname/_design/views/_view/byRubricCategory?key=%5B%229bf94452c27908f241ab559d2a0d46c5%22,%22open%22%5D - 请注意["]都是CGI转义。