用于处理标记标签的 NoSQL 结构
NoSQL Structure for handling labeled tags
目前我有几十万个这样的文件:
{
"_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"
]
}
由于我需要为很多对象添加标签,所以我宁愿首先以最有效的方式进行添加,这样我在不久的将来就不必在开始时回溯 运行 进入问题。
任何指导将不胜感激。
我想到的解决方案是使用 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
您的原始设计(带有标签数组)与 Cloudant Search 配合得很好:https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#search。
使用这种方法,您将定义一个单一的设计文档,该文档将索引标签数组中的任何标签。您不必为不同的标签创建不同的视图,您可以使用 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
目前我有几十万个这样的文件:
{
"_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"
]
}
由于我需要为很多对象添加标签,所以我宁愿首先以最有效的方式进行添加,这样我在不久的将来就不必在开始时回溯 运行 进入问题。
任何指导将不胜感激。
我想到的解决方案是使用 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
您的原始设计(带有标签数组)与 Cloudant Search 配合得很好:https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#search。
使用这种方法,您将定义一个单一的设计文档,该文档将索引标签数组中的任何标签。您不必为不同的标签创建不同的视图,您可以使用 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