Elasticsearch 中的 I18n 搜索和过滤
I18n search and filtering in Elasticsearch
tldr;
如何使用本地化索引匹配和过滤本地化搜索?
长版
我有一个应用程序,用户搜索必须在其语言的上下文中完成。
在弹性搜索索引中,我想要同时具有 i18n 属性和非 i18n 属性的文档(我想避免创建多个索引,每种语言一个)。
文档的映射应如下所示:
'entry': {
'properties': {
'name' : {'type': 'string'}, /* unlocalized properties */
'category': { /* localized properties */
"properties" : {
"lang_fr" : {
"type" : "string"
},
"lang_de" : {
"type" : "string"
}
}
},}}
既然如此,我有两个要求:
1) 匹配: 在进行搜索时,从搜索中排除用户语言不关心的本地化字段(假设用户的语言是 'fr' ,我想从搜索中排除 'de' 个字段。如何在不指定我要搜索的整个字段列表的情况下执行此操作。为了简单起见,我尝试了这个,但它不起作用:
{
"query": {
"match": {
"*.lang_fr": "full_text"
}
}
}
但是,"categories.lang_fr": "full_text"
效果很好。但我不想维护查询中的字段列表。我想要一个通用规则,就像您可以在 SolR 中执行的那样。
2) 过滤: 当我检索结果时,我想过滤掉所有与我的用户语言不对应的本地化字段。换句话说,使用 源过滤器,我想要所有未本地化的字段,排除所有以 "lang" 开头的字段,但包括所有 'lang_fr' 的字段。我尝试了以下但它不起作用:
{
"_source": {
"include": [ "*", "*.lang_fr" ],
"exclude": [ "*.lang_*" ],
}
...}
通配符似乎不起作用。如果我指定 "categories.lang_de"
,我部分得到了我想要的东西,但同样,我不想维护字段列表,我想要一个通用规则。 include/exclude 操作没有像我希望的那样工作。唯一实际有效的是一个查询,我在其中指定要针对所有字段专门排除的所有语言,例如:
{
"_source": {
"exclude": [ "categories.lang_de", "categories.lang_en", "categories.lang_it",
"another_field.lang_de", "catanother_fieldgories.lang_en", "another_field.lang_it"],
}
...}
用于 'fr' 搜索。
我很惊讶我在 google 上找不到任何东西。我将其视为 i18n 应用于 elasticsearch 的一个非常标准的案例。也许我在 ES 中以错误的方式对 i18n 进行了建模?
提前致谢!
您可以使用 query_string
query which takes advantage of the powerful Lucene expression language and allows to specify wildcard in field names:
实现第一个
{
"query": {
"query_string": {
"query": "\*.lang_fr:full_text"
}
}
}
或者你也可以在fields
参数中指定字段名,像这样
{
"query": {
"query_string": {
"query": "full_text"
"fields": ["*.lang_fr"]
}
}
}
至于你的第二个,源过滤确实是可行的方法,但我建议简单地排除除你正在搜索的语言之外的所有语言。例如,如果搜索是法语,您只需排除所有其他语言,而不必枚举所有字段,只需排除所有您不想要的语言(这样会少得多)。这将允许您随时添加本地化字段,而无需更改查询。
{
"_source": {
"exclude": [ "*.lang_de", "*.lang_it" ],
}
...}
tldr;
如何使用本地化索引匹配和过滤本地化搜索?
长版
我有一个应用程序,用户搜索必须在其语言的上下文中完成。
在弹性搜索索引中,我想要同时具有 i18n 属性和非 i18n 属性的文档(我想避免创建多个索引,每种语言一个)。
文档的映射应如下所示:
'entry': {
'properties': {
'name' : {'type': 'string'}, /* unlocalized properties */
'category': { /* localized properties */
"properties" : {
"lang_fr" : {
"type" : "string"
},
"lang_de" : {
"type" : "string"
}
}
},}}
既然如此,我有两个要求:
1) 匹配: 在进行搜索时,从搜索中排除用户语言不关心的本地化字段(假设用户的语言是 'fr' ,我想从搜索中排除 'de' 个字段。如何在不指定我要搜索的整个字段列表的情况下执行此操作。为了简单起见,我尝试了这个,但它不起作用:
{
"query": {
"match": {
"*.lang_fr": "full_text"
}
}
}
但是,"categories.lang_fr": "full_text"
效果很好。但我不想维护查询中的字段列表。我想要一个通用规则,就像您可以在 SolR 中执行的那样。
2) 过滤: 当我检索结果时,我想过滤掉所有与我的用户语言不对应的本地化字段。换句话说,使用 源过滤器,我想要所有未本地化的字段,排除所有以 "lang" 开头的字段,但包括所有 'lang_fr' 的字段。我尝试了以下但它不起作用:
{
"_source": {
"include": [ "*", "*.lang_fr" ],
"exclude": [ "*.lang_*" ],
}
...}
通配符似乎不起作用。如果我指定 "categories.lang_de"
,我部分得到了我想要的东西,但同样,我不想维护字段列表,我想要一个通用规则。 include/exclude 操作没有像我希望的那样工作。唯一实际有效的是一个查询,我在其中指定要针对所有字段专门排除的所有语言,例如:
{
"_source": {
"exclude": [ "categories.lang_de", "categories.lang_en", "categories.lang_it",
"another_field.lang_de", "catanother_fieldgories.lang_en", "another_field.lang_it"],
}
...}
用于 'fr' 搜索。
我很惊讶我在 google 上找不到任何东西。我将其视为 i18n 应用于 elasticsearch 的一个非常标准的案例。也许我在 ES 中以错误的方式对 i18n 进行了建模?
提前致谢!
您可以使用 query_string
query which takes advantage of the powerful Lucene expression language and allows to specify wildcard in field names:
{
"query": {
"query_string": {
"query": "\*.lang_fr:full_text"
}
}
}
或者你也可以在fields
参数中指定字段名,像这样
{
"query": {
"query_string": {
"query": "full_text"
"fields": ["*.lang_fr"]
}
}
}
至于你的第二个,源过滤确实是可行的方法,但我建议简单地排除除你正在搜索的语言之外的所有语言。例如,如果搜索是法语,您只需排除所有其他语言,而不必枚举所有字段,只需排除所有您不想要的语言(这样会少得多)。这将允许您随时添加本地化字段,而无需更改查询。
{
"_source": {
"exclude": [ "*.lang_de", "*.lang_it" ],
}
...}