Database 用于处理标记标签的NoSQL结构

Database 用于处理标记标签的NoSQL结构,database,database-design,relational-database,cloudant,nosql,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" } 目前,我为所有名称编制索引,客户机可以根据文件名搜索文件。这些文件还具有需要与文件关联的标记,但它

目前我有数十万个这样的文件:

{
    "_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" }

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

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

{
    "_id": "11111111",
    "type": "tag",
    "label": "client",
    "items": [
        "1234567890",
        "1222222222",
        "1333333333"
    ]
}
{
  "_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}"
    }
  }
}
由于有很多对象需要添加标记,我宁愿先以最有效的方式添加标记,这样在不久的将来遇到问题时就不必回溯


非常感谢您的指导。

我想到的解决方案是使用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) }}"
        }
    }
}
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
处理视图后,可以使用打开它

GET/YOURDB/\u design/query/\u view/byClient?key=“john”

通过添加查询参数
include\u docs=true
,将返回整个文档,而不是id

也可以将标记写入标记属性,但必须更新映射函数以匹配新设计

有关视图的更多信息,请参见:

您的原始设计带有标记数组,可以很好地与Cloudant搜索配合使用:

使用这种方法,您可以定义一个设计文档,对标记数组中的任何标记进行索引。您不必为不同的标记创建不同的视图,并且可以对查询使用Lucene语法:

因此,以您的示例为例,如果您有一个带有标记的文档,如下所示:

{
  "_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": "11111111",
    "type": "tag",
    "label": "client",
    "items": [
        "1234567890",
        "1222222222",
        "1333333333"
    ]
}
{
  "_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}"
    }
  }
}

谢谢,但我不是在问如何进行搜索,我是在问什么是构建我的数据的最合适的方式,谢谢你的深入回答,我真的很感激。如果我还想让名字可以搜索,只需添加
索引(“name”,doc.name)是否值得在线到if语句上方?或者我应该创建一个全新的索引?我认为将它添加到同一个索引中是有意义的。唯一的问题是,如果您有一个名为“name”的标记,那么您将遇到冲突。不确定那里会发生什么…你就是马克。我一直在视图中使用标准的映射函数,这让我大吃一惊。我不太了解索引是如何工作的,但我非常有兴趣了解执行上述操作与执行类似于
function(doc){emit([doc.timestamp],[doc.u id,doc.type]);}'的操作的区别