node.js - 是否有任何解决方案可以在弹性搜索中搜索确切的单词和包含单词
问题描述
index: process.env.elasticSearchIndexName,
body: {
query: {
bool: {
must: [
{
match_phrase: {
title: `${searchKey}`,
},
},
],
},
},
},
from: (page || constants.pager.page),
size: (limit || constants.pager.limit),
我正在使用上述方法,但问题在于它仅在整个文本中搜索完全匹配的单词。它无法搜索包含单词.. 例如,如果 title = "sweatshirt" 而不是我输入单词 "shirt" 它应该得到结果,但目前使用上述方法没有得到结果
解决方案
标准分析器(如果未指定默认分析器)会破坏标记中的文本。对于句子“这是一个测试”,生成的标记是 [this,is,a,test] Match_pharse 查询使用与索引分析器相同的分析器打破标记中的文本,并返回 1. 包含所有标记 2. 标记以相同顺序出现的文档。
由于您的文本是运动衫,因此倒排索引中有一个标记“运动衫”,它与运动衫或衬衫都不匹配
每当遇到指定字符列表中的一个时,ngram 标记器首先将文本分解为单词,然后发出指定长度的每个单词的 N-gram
映射
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 3,
"max_gram": 3,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings": {
"properties": {
"text":{
"type": "text",
"analyzer": "my_analyzer"
}
}
}
}
询问:
{
"query": {
"match": {
"text": "shirt"
}
}
}
如果您将运行 _analyze 查询
GET my_index/_analyze
{
"text": ["sweatshirt"],
"analyzer": "my_analyzer"
}
您将看到为文本运动衫生成了下面的令牌。可以使用 min_gram 和 max_gram 调整令牌的大小
{
"tokens" : [
{
"token" : "swe",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "wea",
"start_offset" : 1,
"end_offset" : 4,
"type" : "word",
"position" : 1
},
{
"token" : "eat",
"start_offset" : 2,
"end_offset" : 5,
"type" : "word",
"position" : 2
},
{
"token" : "ats",
"start_offset" : 3,
"end_offset" : 6,
"type" : "word",
"position" : 3
},
{
"token" : "tsh",
"start_offset" : 4,
"end_offset" : 7,
"type" : "word",
"position" : 4
},
{
"token" : "shi",
"start_offset" : 5,
"end_offset" : 8,
"type" : "word",
"position" : 5
},
{
"token" : "hir",
"start_offset" : 6,
"end_offset" : 9,
"type" : "word",
"position" : 6
},
{
"token" : "irt",
"start_offset" : 7,
"end_offset" : 10,
"type" : "word",
"position" : 7
}
]
}
警告:Ngrams 会增加倒排索引的大小,因此请使用适当的 min_gram 和 max_gram 值
另一种选择是使用通配符查询。对于通配符,必须扫描所有文档以检查文本是否与模式匹配。它们的性能低下。在 not_analyzed 字段上使用通配符搜索时,如果您想包含空格 ex text.keyword
{
"query": {
"wildcard": {
"text": {
"value": "*shirt*"
}
}
}
}
推荐阅读
- mysql - MySQL 行大小太大,但仅在 5.7
- javascript - 具有网格布局的可重用 Vue JS 搜索过滤器
- swift - 实施了帮助应用程序,但在登录时未启动
- javascript - React.js 中的奇怪错误——Fetch API 正在从 index.html 返回 HTML,尽管没有被调用
- php - Mailgun 拒绝服务器上的一些电子邮件
- sql-server - 如何将旧视图从 SQL Query 卸载到脚本
- json - Angular 2+:如何使用来自后端的数据实例化一个类?
- sql - 优化 postgresDB 上的 sql 查询
- swift - Deleted tableviewcell gets replaced by last cell
- android - 自动保存共享首选项