elasticsearch - 如何使用 elasticsearch nest api 创建自定义分析器以忽略重音和 pt-br 停用词?
问题描述
首先,考虑我正在使用一个“新闻”类(葡萄牙语中的 Noticia),它有一个名为“内容”的字符串字段(葡萄牙语中的 Conteudo)
public class Noticia
{
public string Conteudo { get; set; }
}
我正在尝试创建一个索引,该索引被配置为忽略重音和 pt-br 停用词,并允许在高亮查询中分析多达 40mi 的字符。
我可以使用以下代码创建这样的索引:
var createIndexResponse = client.Indices.Create(indexName, c => c
.Settings(s => s
.Setting("highlight.max_analyzed_offset" , 40000000)
.Analysis(analysis => analysis
.TokenFilters(tokenfilters => tokenfilters
.AsciiFolding("folding-accent", ft => ft
)
.Stop("stoping-br", st => st
.StopWords("_brazilian_")
)
)
.Analyzers(analyzers => analyzers
.Custom("folding-analyzer", cc => cc
.Tokenizer("standard")
.Filters("folding-accent", "stoping-br")
)
)
)
)
.Map<Noticia>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Conteudo)
.Analyzer("folding-analyzer")
)
)
)
);
如果我使用 Kibana 开发工具测试这个分析器,我会得到我想要的结果:没有重音符号和停用词被删除!
POST intranet/_analyze
{
"analyzer": "folding-analyzer",
"text": "Férias de todos os funcionários"
}
结果:
{
"tokens" : [
{
"token" : "Ferias",
"start_offset" : 0,
"end_offset" : 6,
"type" : "<ALPHANUM>",
"position" : 0
},
{
"token" : "funcionarios",
"start_offset" : 19,
"end_offset" : 31,
"type" : "<ALPHANUM>",
"position" : 4
}
]
}
当我使用 NEST 使用折叠分析器分析查询时,返回相同(良好)的结果(返回令牌“Ferias”和“funcionarios”)
var analyzeResponse = client.Indices.Analyze(a => a
.Index(indexName)
.Analyzer("folding-analyzer")
.Text("Férias de todos os funcionários")
);
但是,如果我使用 NEST ElasticSearch .NET 客户端执行搜索,则“Férias”(带口音)和“Ferias”(不带口音)之类的术语将被视为不同。
我的目标是执行一个返回所有结果的查询,无论这个词是 Férias 还是 Ferias
这就是我用来查询弹性搜索的简化代码(C# 嵌套):
var searchResponse = ElasticClient.Search<Noticia>(s => s
.Index(indexName)
.Query(q => q
.MultiMatch(m => m
.Fields(f => f
.Field(p => p.Titulo,4)
.Field(p => p.Conteudo,2)
)
.Query(termo)
)
)
);
这就是与 searchResponse 关联的扩展 API 调用
Successful (200) low level call on POST: /intranet/_search?pretty=true&error_trace=true&typed_keys=true
# Audit trail of this API call:
- [1] HealthyResponse: Node: ###NODE ADDRESS### Took: 00:00:00.3880295
# Request:
{"query":{"multi_match":{"fields":["categoria^1","titulo^4","ementa^3","conteudo^2","attachments.attachment.content^1"],"query":"Ferias"}},"size":100}
# Response:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 13.788051,
"hits" : [
{
"_index" : "intranet",
"_type" : "_doc",
"_id" : "4934",
"_score" : 13.788051,
"_source" : {
"conteudo" : "blablabla ferias blablabla",
"attachments" : [ ],
"categoria" : "Novidades da Biblioteca - DBD",
"publicadaEm" : "2008-10-14T00:00:00",
"titulo" : "INFORMATIVO DE DIREITO ADMINISTRATIVO E LRF - JUL/2008",
"ementa" : "blablabla",
"matriculaAutor" : 900794,
"atualizadaEm" : "2009-02-03T13:44:00",
"id" : 4934,
"indexacaoAtiva" : true,
"status" : "Disponível"
}
}
]
}
}
我也尝试在查询中使用多字段和后缀,但没有成功
.Map<Noticia>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Conteudo)
.Analyzer("folding-analyzer")
.Fields(f => f
.Text(ss => ss
.Name("folding")
.Analyzer("folding-analyzer")
)
)
(...)
var searchResponse = ElasticClient.Search<Noticia>(s => s
.Index(indexName)
.Query(q => q
.MultiMatch(m => m
.Fields(f => f
.Field(p => p.Titulo,4)
.Field(p => p.Conteudo.Suffix("folding"),2)
)
.Query(termo)
)
)
);
任何线索我做错了什么或我可以做些什么来达到我的目标?
提前非常感谢!
解决方案
几天后,我发现我做错了什么,这都是关于映射的。
这是我解决问题并最终解决问题所采取的步骤
1 - 首先我打开了 kibana 控制台,发现只有我的映射字段的最后一个字段被分配给我的自定义分析器(折叠分析器)
要测试每个字段,您可以使用 GET FIELD MAPPING API 和开发工具中的命令,如下所示:
GET /<index>/_mapping/field/<field>
那么您将能够查看您的分析仪是否已分配给您的字段
2 - 之后,我发现最后一个字段是唯一分配给我的自定义分析器的字段,原因是我以两种方式弄乱了流畅的映射:
- 首先,我必须正确链接我的文本属性
- 其次,当我应该使用 Object<> 子句时,我试图在另一个 Map<> 子句中映射另一个 POCO 类
对我有用的正确映射有点像这样:
.Map<Noticia>(mm => mm
.AutoMap()
.Properties(p => p
.Text(t => t
.Name(n => n.Field1)
.Analyzer("folding-analyzer")
)
.Text(t => t
.Name(n => n.Field2)
.Analyzer("folding-analyzer")
)
.Object<NoticiaArquivo>(o => o
.Name(n => n.Arquivos)
.Properties(eps => eps
.Text(s => s
.Name(e => e.NAField1)
.Analyzer("folding-analyzer")
)
.Text(s => s
.Name(e => e.NAField2)
.Analyzer("folding-analyzer")
)
)
)
)
)
最后,重要的是要分享,当您使用 .Analyzer("analiserName") 子句分配分析器时,您是在告诉弹性搜索您希望将参数分析器用于索引和搜索
如果您只想在搜索时而不是在索引时使用分析器,则应使用 .SearchAnalyzer("analiserName") 子句。
推荐阅读
- python - 当我在 Python Tutor 上运行代码时,我的代码一直显示错误:“太多无法解包”。如何修复此错误?
- postgresql - 如何根据postgres中的列名更新列?
- maven - 无法检查 Maven 版本
- angular - 如何将类添加到 Angular 的 ngFor 中间元素或默认类
- reactjs - 反应:未捕获的类型错误:无法读取未定义的属性“应用程序”
- react-native - 如何制作反应原生甲板动画?
- java - Hadoop:如何通过现代 API(2.7+)启用中间数据压缩?
- javascript - onclick 事件未触发且下拉代码不起作用
- r - 加载内置数据时出现knitr错误
- node.js - 在通过云函数在 Firestore 中进行更改后从文档中检索对象数组