单个字段的 Elasticsearch 多个分析器
Elasticsearch multiple analyzers for a single field
我使用严格的预定义映射将不同类型的文档存储在单个索引中。它们都有一些字段(例如,"body"),但我希望在索引时对它们进行稍微不同的分析(例如,对特定文档使用不同的标记过滤器)并在搜索时以相同的方式处理。据我所知,无法为每个文档指定分析器。
我也考虑过用什么:
- 具有针对文档类型的不同分析子字段的对象字段,因此每个文档只有一个填充的子字段(例如,"body.mail"、"body.html")。问题是我无法搜索整个 "body" 字段,它会查看其所有子字段(不破坏现有应用程序)。
- 多字段的新轮回(具有带有通用分析器的 "body" 字段,并在其中自定义分析 "mail"、"html" 等)。 Hovewer,我不确定是否可以在索引时直接使用它们并在搜索时间接使用它们(例如,使用
{"mail":"smth"}
保存对象以使用特定的索引分析器,然后通过 "query":{"body":"smth"}
搜索以使用通用搜索分析器)。
- 要将 "body" 分成多个具有不同映射的字段,请将它们从
_all
中删除,并将 copy_to
设置为单个 body
字段。我不确定,但由于复制,它会增加大量索引开销。
我认为你可以使用多字段。使用多字段,您可以为每个子字段定义分析器(包括索引和搜索),并根据应用程序需求对相应字段进行搜索。
一般来说,索引分析器会因字段而异,搜索分析器也一样。
{
"your_type" : {
"properties":{
"body" : {
"type" : "string",
"index" : "analyzed",
"index_analyzer" : "index_body_analyzer",
"search_analyzer" : "search_body_analyzer",
"fields" : {
"mail" : {
"type" : "string",
"index" : "analyzed",
"index_analyzer" : "index_bodymail_analyzer",
"search_analyzer" : "search_bodymail_analyzer"
},
"html": {
"type" : "string",
"index" : "analyzed",
"index_analyzer" : "index_bodyhtml_analyzer",
"search_analyzer" : "search_bodyhtml_analyzer"
}
}
}
}
}
正如我在评论中提到的,你想要的是不可能的。一句话,您的要求是:以多种方式分析相同的数据,但作为单个字段进行搜索,因为这会破坏现有的应用程序。
-- body.html
-- body.email
body field ---- body.content --- all searched as "body"
...
-- body.destination
-- body.whatever
您的第一个选择是 多字段,它的确切目的是:以多种方式分析相同的数据。问题是您不能搜索 "body"
并期望 ES 搜索 body.html
、body.email
... 即使这是可能的,您也希望使用不同的分析器进行搜索。再次,不可能。此选项要求您 更改应用程序 并在 multi_match
或 query_string
.
中搜索每个字段
您的第二个选项 - reincarnation of multi-fields
- 将再次无效,因为 您无法在后台引用 body
和 ES 来匹配 mail
、content
等
第三个选项 - 使用 copy_to
- 将不起作用,因为复制到另一个字段 "X" 意味着索引正在复制的数据 将使用 X
的分析器,这打破了您对相同数据进行不同分析的要求。
可能还有第四个选项 - "path": "just_name"
from multi_fields
- 乍一看应该可行。也就是说,您可以有 3 个多字段(电子邮件、内容、html),这三个字段都有一个 body
子字段。拥有 "path": "just_name"
允许您仅搜索 body
,即使 body
是多个其他字段的子字段。但这是不可能的,因为这种类型的多字段 不会接受相同 body
.
的不同分析器
无论哪种方式,您都需要更改您的要求,因为它们不会按照您想要的方式工作。
话虽如此,我很想知道您在应用程序中使用了哪些查询。这将是一个简单的更改(是的,您需要将您的应用程序)从查询 body
字段更改为在 multi_match
中查询 body.*
。
我为您提供了另一种解决方案:创建多个索引,为您 body
的每个分析器创建一个索引。例如,对于 mail
、content
和 html
,您定义了三个索引:
PUT /multi_fields1
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "whitespace",
"search_analyzer": "standard"
}
}
}
}
}
PUT /multi_fields2
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "standard",
"search_analyzer": "standard"
}
}
}
}
}
PUT /multi_fields3
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "keyword",
"search_analyzer": "standard"
}
}
}
}
}
您看到它们都具有相同的 type
和相同的字段名称 - body
- 但不同的 index_analyzer
。然后你定义一个别名:
POST _aliases
{
"actions": [
{"add": {
"index": "multi_fields1",
"alias": "multi"}},
{"add": {
"index": "multi_fields2",
"alias": "multi"}},
{"add": {
"index": "multi_fields3",
"alias": "multi"}}
]
}
将别名命名为与当前索引相同的别名。应用程序不需要更改,它将使用相同的名称进行索引搜索,但是此名称不会指向索引,而是指向一个别名,该别名又指向您的多个指数。需要改变的是如何索引文档,因为 html
文档需要进入 multi_fields1
索引,例如 email
文档需要在 multi_fields2
索引中进行索引等等
无论您 find/choose 是什么解决方案,您的要求都需要改变,因为您想要的方式是不可能的。
我使用严格的预定义映射将不同类型的文档存储在单个索引中。它们都有一些字段(例如,"body"),但我希望在索引时对它们进行稍微不同的分析(例如,对特定文档使用不同的标记过滤器)并在搜索时以相同的方式处理。据我所知,无法为每个文档指定分析器。
我也考虑过用什么:
- 具有针对文档类型的不同分析子字段的对象字段,因此每个文档只有一个填充的子字段(例如,"body.mail"、"body.html")。问题是我无法搜索整个 "body" 字段,它会查看其所有子字段(不破坏现有应用程序)。
- 多字段的新轮回(具有带有通用分析器的 "body" 字段,并在其中自定义分析 "mail"、"html" 等)。 Hovewer,我不确定是否可以在索引时直接使用它们并在搜索时间接使用它们(例如,使用
{"mail":"smth"}
保存对象以使用特定的索引分析器,然后通过"query":{"body":"smth"}
搜索以使用通用搜索分析器)。 - 要将 "body" 分成多个具有不同映射的字段,请将它们从
_all
中删除,并将copy_to
设置为单个body
字段。我不确定,但由于复制,它会增加大量索引开销。
我认为你可以使用多字段。使用多字段,您可以为每个子字段定义分析器(包括索引和搜索),并根据应用程序需求对相应字段进行搜索。 一般来说,索引分析器会因字段而异,搜索分析器也一样。
{ "your_type" : { "properties":{ "body" : { "type" : "string", "index" : "analyzed", "index_analyzer" : "index_body_analyzer", "search_analyzer" : "search_body_analyzer", "fields" : { "mail" : { "type" : "string", "index" : "analyzed", "index_analyzer" : "index_bodymail_analyzer", "search_analyzer" : "search_bodymail_analyzer" }, "html": { "type" : "string", "index" : "analyzed", "index_analyzer" : "index_bodyhtml_analyzer", "search_analyzer" : "search_bodyhtml_analyzer" } } } } }
正如我在评论中提到的,你想要的是不可能的。一句话,您的要求是:以多种方式分析相同的数据,但作为单个字段进行搜索,因为这会破坏现有的应用程序。
-- body.html
-- body.email
body field ---- body.content --- all searched as "body"
...
-- body.destination
-- body.whatever
您的第一个选择是 多字段,它的确切目的是:以多种方式分析相同的数据。问题是您不能搜索
"body"
并期望 ES 搜索body.html
、body.email
... 即使这是可能的,您也希望使用不同的分析器进行搜索。再次,不可能。此选项要求您 更改应用程序 并在multi_match
或query_string
. 中搜索每个字段
您的第二个选项 -
reincarnation of multi-fields
- 将再次无效,因为 您无法在后台引用body
和 ES 来匹配mail
、content
等第三个选项 - 使用
copy_to
- 将不起作用,因为复制到另一个字段 "X" 意味着索引正在复制的数据 将使用X
的分析器,这打破了您对相同数据进行不同分析的要求。可能还有第四个选项 -
"path": "just_name"
frommulti_fields
- 乍一看应该可行。也就是说,您可以有 3 个多字段(电子邮件、内容、html),这三个字段都有一个body
子字段。拥有"path": "just_name"
允许您仅搜索body
,即使body
是多个其他字段的子字段。但这是不可能的,因为这种类型的多字段 不会接受相同body
. 的不同分析器
无论哪种方式,您都需要更改您的要求,因为它们不会按照您想要的方式工作。
话虽如此,我很想知道您在应用程序中使用了哪些查询。这将是一个简单的更改(是的,您需要将您的应用程序)从查询 body
字段更改为在 multi_match
中查询 body.*
。
我为您提供了另一种解决方案:创建多个索引,为您 body
的每个分析器创建一个索引。例如,对于 mail
、content
和 html
,您定义了三个索引:
PUT /multi_fields1
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "whitespace",
"search_analyzer": "standard"
}
}
}
}
}
PUT /multi_fields2
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "standard",
"search_analyzer": "standard"
}
}
}
}
}
PUT /multi_fields3
{
"mappings": {
"test": {
"properties": {
"body": {
"type": "string",
"index_analyzer": "keyword",
"search_analyzer": "standard"
}
}
}
}
}
您看到它们都具有相同的 type
和相同的字段名称 - body
- 但不同的 index_analyzer
。然后你定义一个别名:
POST _aliases
{
"actions": [
{"add": {
"index": "multi_fields1",
"alias": "multi"}},
{"add": {
"index": "multi_fields2",
"alias": "multi"}},
{"add": {
"index": "multi_fields3",
"alias": "multi"}}
]
}
将别名命名为与当前索引相同的别名。应用程序不需要更改,它将使用相同的名称进行索引搜索,但是此名称不会指向索引,而是指向一个别名,该别名又指向您的多个指数。需要改变的是如何索引文档,因为 html
文档需要进入 multi_fields1
索引,例如 email
文档需要在 multi_fields2
索引中进行索引等等
无论您 find/choose 是什么解决方案,您的要求都需要改变,因为您想要的方式是不可能的。