如何在 ElasticSearch 中对层次结构进行非规范化?
How to denormalize hierarchy in ElasticSearch?
我是 ElasticSearch 的新手,我有一棵树,它描述了某个文档的路径(不是真正的文件系统路径,只是将文章、图像、文档归类为一个的简单文本字段)。每个路径条目都有一个类型,例如:Group Name
、Assembly name
甚至 Unknown
。例如,这些类型可用于查询以跳过路径中的某些条目。
我的源数据存储在 SQL 服务器中,架构如下所示:
通过将 Tree.Id
连接到 Tree.ParentId
来构建树,但每个节点都必须有一个类型。文档连接到树中的叶子。
我不担心在 SQL 服务器中查询结构,但是我应该找到一种最佳方法来在 Elastic 中对它们进行非规范化和搜索。如果我展平路径并为文档创建一个 "descriptors" 列表,我可以将每个文档条目存储为一个弹性文档。:
{
"path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
"descriptors": [
{
"name": "NodeNameRoot",
"type": "type1"
},
{
"name": "NodeNameLevel_1",
"type": "type1"
},
{
"name": "NodeNameLevel_2",
"type": "type2"
},
{
"name": "NodeNameLevel_3",
"type": "type2"
},
{
"name": "NodeNameLevel_4",
"type": "type3"
}
],
"document": {
...
}
}
我可以在ElasticSearch中查询这样的结构吗?或者我应该以不同的方式对路径进行非规范化吗?
我的主要问题:
可以根据类型或文本值查询它们(例如正则表达式匹配)。例如:给我所有 type2->type3 路径(实际上将 type1 排除在外),其中路径包含 X
?
是否可以按级别查询?就像我想要有 4 个描述符的路径一样。
我可以使用 built-in 功能进行搜索还是需要编写扩展程序?
编辑
根据 G Quintana 的答案,我做了一个这样的索引。:
curl -X PUT \
http://localhost:9200/test \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"mappings": {
"path": {
"properties": {
"names": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"tokens": {
"type": "text",
"analyzer": "pathname_analyzer"
},
"depth": {
"type": "token_count",
"analyzer": "pathname_analyzer"
}
}
},
"types": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"tokens": {
"type": "text",
"analyzer": "pathname_analyzer"
}
}
}
}
}
},
"settings": {
"analysis": {
"analyzer": {
"pathname_analyzer": {
"type": "pattern",
"pattern": "#->>",
"lowercase": true
}
}
}
}
}'
并且可以这样查询深度。:
curl -X POST \
http://localhost:9200/test/path/_search \
-H 'content-type: application/json' \
-d '{
"query": {
"bool": {
"should": [
{"match": { "names.depth": 5 }}
]
}
}
}'
其中 return 结果正确。我会再测试一下。
首先,您应该确定所有查询模式以设计您将如何为数据编制索引。
根据您给出的示例,我将索引以下形式的文档:
{
"path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
"types: "type1/type1/type2/type2/type3",
"document": {
...
}
}
在建立索引之前,您必须配置映射和分析:
- 字段
path
:
- 使用类型
text
+ 基于 pattern analyzer 的分析器在 /
个字符处拆分
- 使用类型
token_count
+ same analyzer to compute path depth. Create a multi field (path.depth
)
- 字段
types
- 使用类型
text
+ 基于 pattern analyzer 的分析器在 /
个字符处拆分
配置索引映射和分析以拆分 path
和 types
字段,并使用 a 或 a
- 给我所有 type2->type3 路径 在
types
字段上使用 match_phrase
查询
- 其中路径包含 X 在
path
字段上使用 match
查询
- 其中有 4 个描述符 在
path.depth
子字段上使用 term
查询
您的描述符字段没有意义。
Path tokenizer 对于某些用例可能很有趣。
您可以使用 multi-fields 在同一字段上应用多个分析器,然后查询是否有子字段。
我是 ElasticSearch 的新手,我有一棵树,它描述了某个文档的路径(不是真正的文件系统路径,只是将文章、图像、文档归类为一个的简单文本字段)。每个路径条目都有一个类型,例如:Group Name
、Assembly name
甚至 Unknown
。例如,这些类型可用于查询以跳过路径中的某些条目。
我的源数据存储在 SQL 服务器中,架构如下所示:
通过将 Tree.Id
连接到 Tree.ParentId
来构建树,但每个节点都必须有一个类型。文档连接到树中的叶子。
我不担心在 SQL 服务器中查询结构,但是我应该找到一种最佳方法来在 Elastic 中对它们进行非规范化和搜索。如果我展平路径并为文档创建一个 "descriptors" 列表,我可以将每个文档条目存储为一个弹性文档。:
{
"path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
"descriptors": [
{
"name": "NodeNameRoot",
"type": "type1"
},
{
"name": "NodeNameLevel_1",
"type": "type1"
},
{
"name": "NodeNameLevel_2",
"type": "type2"
},
{
"name": "NodeNameLevel_3",
"type": "type2"
},
{
"name": "NodeNameLevel_4",
"type": "type3"
}
],
"document": {
...
}
}
我可以在ElasticSearch中查询这样的结构吗?或者我应该以不同的方式对路径进行非规范化吗?
我的主要问题:
可以根据类型或文本值查询它们(例如正则表达式匹配)。例如:给我所有 type2->type3 路径(实际上将 type1 排除在外),其中路径包含 X
?
是否可以按级别查询?就像我想要有 4 个描述符的路径一样。
我可以使用 built-in 功能进行搜索还是需要编写扩展程序?
编辑 根据 G Quintana 的答案,我做了一个这样的索引。:
curl -X PUT \
http://localhost:9200/test \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"mappings": {
"path": {
"properties": {
"names": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"tokens": {
"type": "text",
"analyzer": "pathname_analyzer"
},
"depth": {
"type": "token_count",
"analyzer": "pathname_analyzer"
}
}
},
"types": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"tokens": {
"type": "text",
"analyzer": "pathname_analyzer"
}
}
}
}
}
},
"settings": {
"analysis": {
"analyzer": {
"pathname_analyzer": {
"type": "pattern",
"pattern": "#->>",
"lowercase": true
}
}
}
}
}'
并且可以这样查询深度。:
curl -X POST \
http://localhost:9200/test/path/_search \
-H 'content-type: application/json' \
-d '{
"query": {
"bool": {
"should": [
{"match": { "names.depth": 5 }}
]
}
}
}'
其中 return 结果正确。我会再测试一下。
首先,您应该确定所有查询模式以设计您将如何为数据编制索引。
根据您给出的示例,我将索引以下形式的文档:
{
"path": "NodeNameRoot/NodeNameLevel_1/NodeNameLevel_2/NodeNameLevel_3/NodeNameLevel_4",
"types: "type1/type1/type2/type2/type3",
"document": {
...
}
}
在建立索引之前,您必须配置映射和分析:
- 字段
path
:- 使用类型
text
+ 基于 pattern analyzer 的分析器在/
个字符处拆分 - 使用类型
token_count
+ same analyzer to compute path depth. Create a multi field (path.depth
)
- 使用类型
- 字段
types
- 使用类型
text
+ 基于 pattern analyzer 的分析器在/
个字符处拆分
- 使用类型
配置索引映射和分析以拆分 path
和 types
字段,并使用 a 或 a
- 给我所有 type2->type3 路径 在
types
字段上使用match_phrase
查询 - 其中路径包含 X 在
path
字段上使用match
查询 - 其中有 4 个描述符 在
path.depth
子字段上使用term
查询
您的描述符字段没有意义。 Path tokenizer 对于某些用例可能很有趣。 您可以使用 multi-fields 在同一字段上应用多个分析器,然后查询是否有子字段。