用于处理带标签标签的NoSQL结构

时间:2017-04-05 19:46:19

标签: database database-design relational-database cloudant nosql

目前我有成千上万的文件,如下:

{
    "_id": "1234567890",
    "type": "file",
    "name": "Demo File",
    "file_type": "application/pdf",
    "size": "1400",
    "timestamp": "1491421149",
    "folder_id": "root"
}

目前,我索引所有名称,客户端可以根据文件名搜索文件。这些文件还有tags需要与文件关联,但它们也有特定的标签。

一个例子是:

{
    "tags": [
        { "client": "john doe" },
        { "office": "virginia" },
        { "ssn": "1234" }

    ]
}

如果我希望能够使用 John Doe 的客户端搜索数千个文件,那么将tags数组添加到我的上述文件对象是理想的解决方案吗?

我能想到的唯一其他解决方案是每个标签都有一个对象,并且每个标签都有一个文件ID数组,如下所示:

{
    "_id": "11111111",
    "type": "tag",
    "label": "client",
    "items": [
        "1234567890",
        "1222222222",
        "1333333333"
    ]
}

由于这是我需要添加标签的大量对象,我宁愿以最有效的方式做到这一点,所以我不必在不久的将来回溯,当我开始遇到的问题。

非常感谢任何指导。

2 个答案:

答案 0 :(得分:1)

您的原始设计(带有标签数组)适用于Cloudant Search:https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#search

使用这种方法,您可以定义一个设计文档,该文档将索引tags数组中的任何标记。您不必为不同的标记创建不同的视图,您可以使用Lucene语法进行查询:http://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Overview

因此,使用您的示例,如果您的文档看起来像带有标记:

{
  "_id": "1234567890",
  "type": "file",
  "name": "Demo File",
  "file_type": "application/pdf",
  "size": "1400",
  "timestamp": "1491421149",
  "folder_id": "root",
  "tags": [
    { "client": "john doe" },
    { "office": "virginia" },
    { "ssn": "1234" }
  ]
}

您可以创建一个设计文档,为每个标记编制索引,如下所示:

{
  "_id": "_design/searchFiles",
  "views": {},
  "language": "javascript",
  "indexes": {
    "byTag": {
      "analyzer": "standard",
      "index": "function (doc) {\n  if (doc.type === \"file\" && doc.tags) {\n    for (var i=0; i<doc.tags.length; i++) {\n      for (var name in doc.tags[i]) {\n        index(name, doc.tags[i][name]);\n      }\n    }\n  }\n}"
    }
  }
}

该功能如下所示:

function (doc) {
  if (doc.type === "file" && doc.tags) {
    for (var i=0; i<doc.tags.length; i++) {
      for (var name in doc.tags[i]) {
        index(name, doc.tags[i][name]);
      }
    }
  }
}

然后你会这样搜索:

https://your_cloudant_account.cloudant.com/your_db/_design/searchFiles/_search/byTag
?q=client:jack+OR+office:virginia
&include_docs=true

答案 1 :(得分:0)

我想到的解决方案是使用map reduce函数。

为此,您可以将标签添加到原始文档中:

{
    "_id": "1234567890",
    "type": "file",
    "name": "Demo File",
    "file_type": "application/pdf",
    "size": "1400",
    "timestamp": "1491421149",
    "folder_id": "root",
    "client": "john",
    ...
}

之后,您可以创建一个如下所示的设计文档:

{
    "_id": "_design/query",
    "views": {
        "byClient": {
            "map": "function(doc) { if(doc.client) { emit(doc.client, doc._id) }}"
        }
    }
}

处理完视图后,您可以使用

打开它

GET /YOURDB/_design/query/_view/byClient?key="john"

通过添加查询参数include_docs=true,将返回整个文档,而不是id。

您也可以将标签写入标签属性,但必须更新地图功能以匹配新设计。

有关视图的更多信息,请访问: http://docs.couchdb.org/en/2.0.0/api/ddoc/views.html