javascript - 使用来自 elasticsearch 的通配符搜索完整和部分文本值
问题描述
我有下面的简单表格,其中包含来自 elasticsearch 的标题和代码列,如下所示
{ title: 'test1', code: 'ZjS3d3k8z',... },
{ title: 'test2 with more words', code: 'AjS3d2k1z',... }
我正在尝试使用通配符过滤标题和代码,如下所示,
{
"sort": [
{
"creation_date": {
"order": "desc"
}
},
"_score"
],
"query": {
"bool": {
"must": [
{
"match": {
"account_id": 100
}
}
],
"should": [
{
"wildcard": {
"code": "?test2 with"
}
},
{
"wildcard": {
"title": "*test2 with*"
}
}
],
"minimum_number_should_match": 1
}
}
}
上述查询适用于预期结果/失败,在以下情况下没有结果
> 'test1' <---- works(return expected result) when i try to search single word
> 'test2' <---- works(return expected result) when i try to search single word
> 'test2 with'<---- fails(return empty result) when i try to search more than one word with space'
> 'test2 with more words' <---- fails(return empty result) when i try to search full title
当我尝试如下搜索代码时,它总是返回空结果!!!
"should": [
{
"wildcard": {
"code": "?ZjS3d3k8z"
}
},
{
"wildcard": {
"title": "*ZjS3d3k8z*"
}
}
]
我想使用弹性搜索从数百万条记录中搜索具有部分/全部价值的标题/代码。好心提醒。
解决方案
对于通配符,在 "keyword" 字段而不是 "text" 上执行搜索。对于文本数据类型,分析字符串,分解为标记,同时按原样存储关键字字段。"test2 with more words" 存储为 ["test2","with","more","words"] 并且您的通配符输入与这些标记匹配,因此不返回任何文档。
{
"query": {
"bool": {
"should": [
{
"wildcard": {
"code.keyword": "*test2 with*"
}
},
{
"wildcard": {
"title.keyword": "*test2 with*"
}
}
],
"minimum_should_match": 1
}
}
}
使用动态模板创建的映射具有每种文本类型的关键字子字段。如果您已显式创建映射,则需要添加关键字子字段
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "text"
}
}
}
外卡性能较差,有更好的选择。
- Match/Match_phrase/Match_phrase_prefix
如果您正在搜索诸如“test2 with”之类的整个令牌。您可以简单地进行匹配查询,将返回所有包含标记“test2”和“with”的文档
"should": [
{
"match": {
"code": {
"query": "test2 with",
"operator": "and"
}
}
},
{
"match": {
"title": {
"query": "test2 with",
"operator": "and"
}
}
}
]
如果令牌的顺序很重要,您可以使用 match_phrase。
如果要搜索部分标记,请使用 match_phrase_prefix。前缀匹配仅在搜索输入 ex 中的最后一个标记上完成。“测试2 w”
每当遇到指定字符列表中的一个时,edge_ngram 标记器首先将文本分解为单词,然后它发出每个单词的 N-gram,其中 N-gram 的开头锚定到单词的开头。
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 10,
"token_chars": [
"letter",
"digit"
]
}
}
}
}
}
生成的令牌:
"tokens" : [
{
"token" : "te",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "tes",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 1
},
{
"token" : "test",
"start_offset" : 0,
"end_offset" : 4,
"type" : "word",
"position" : 2
},
{
"token" : "test2",
"start_offset" : 0,
"end_offset" : 5,
"type" : "word",
"position" : 3
},
{
"token" : "wi",
"start_offset" : 6,
"end_offset" : 8,
"type" : "word",
"position" : 4
},
{
"token" : "wit",
"start_offset" : 6,
"end_offset" : 9,
"type" : "word",
"position" : 5
},
{
"token" : "with",
"start_offset" : 6,
"end_offset" : 10,
"type" : "word",
"position" : 6
}
]
这将让您执行像“tes wit”这样的搜索,即任何标记都可以是部分的,不像 match_phrase_prefix 只对最后一个标记进行前缀搜索
每当遇到指定字符列表中的一个时,ngram 标记器首先将文本分解为单词,然后发出指定长度的每个单词的 N-gram。
N-gram 就像一个在单词上移动的滑动窗口 - 指定长度的连续字符序列
即使在中间“est”匹配测试中,您也可以搜索部分标记
- 建议 者他们在您键入时提供搜索功能
您可以根据您的要求选择其中任何一个
推荐阅读
- exe - 如何使可执行文件仅以管理员身份运行(exe 上的 UAC 图标)
- ios - 如何在表格视图中更新集合视图中的数据?
- javascript - 如何获取实际的客户端 URL?
- node.js - 导出 firebaseui 的导入节点模块导致玩笑测试失败,并显示“ReferenceError:未定义窗口”
- android - Android内容Uri不能被其他应用播放
- javascript - 我使用 insertBefore dom 方法在另一个元素之前插入一个元素。但它根本不起作用
- javascript - 如何限制对象Javascript中的元素
- python - 反转随机生成函数
- python - 如何在命令后在 discord.py 中获取用户输入
- android - 使用一个 java 类处理多个资源布局