【发布时间】:2019-01-04 03:38:25
【问题描述】:
使用 Hibernate Search (5.8.2.Final) 查询 DSL 到 Elasticsearch 服务器。
给定一个执行小写、标准停用词的字段分析器,然后是自定义同义词:
company => co
最后,自定义停用词:
co
我们已经索引了一个供应商名称:Great Spaulding Company,它在 Elasticsearch 中归结为同义词和停用词后的 2 个术语:great 和 spaulding。
我正在尝试构建我的查询,以便每个术语“必须”匹配,模糊或精确,具体取决于术语长度。
我得到了我想要的结果,除非其中一个术语恰好是同义词或停用词并且足够长以至于我的代码为其添加了模糊性,例如company~1,在这种情况下,它不再被视为同义词或停用词,我的查询不返回匹配项,因为“公司”从未存储在第一位 b/c 它变成“co”,然后作为停用词被删除。
是时候写一些代码了。这可能看起来有点老套,但我尝试了很多方法,并使用simpleQueryString 和withAndAsDefaultOperator 并构建我自己的短语似乎让我最接近我需要的结果(但我愿意接受建议)。我正在做类似的事情:
// assume passed in search String of "Great Spaulding Company"
String vendorName = "Great Spaulding Company";
List<String> vendorNameTerms = Arrays.asList(vendorName.split(" "));
List<String> qualifiedTerms = Lists.newArrayList();
vendorNameTerms.forEach(term -> {
int editDistance = getEditDistance(term); // 1..5 = 0, 6..10 = 1, > 10 = 2
int prefixLength = getPrefixLength(term); //appears of no use with simpleQueryString
String fuzzyMarker = editDistance > 0 ? "~" + editDistance : "";
qualifiedTerms.add(String.format("%s%s", term, fuzzyMarker));
});
// join my terms back together with their optional fuzziness marker
String phrase = qualifiedTerms.stream().collect(Collectors.joining(" "));
bool.should(
qb.simpleQueryString()
.onField("vendorNames.vendorName")
.withAndAsDefaultOperator()
.matching(phrase)
.createQuery()
);
如上所述,我发现只要不对可能的同义词或停用词添加任何模糊性,查询就会找到匹配项。所以这些短语返回匹配:
"Great Spaulding~1" 或 "Great Spaulding~1 Co" 或 "Spaulding Co"
但是由于我的代码不知道哪些术语是同义词或停用词,它会盲目地查看术语长度并说,哦,'Company' 大于 5 个字符,我会使其模糊,它构建了这些不返回匹配项的各种短语:
"Great Spaulding~1 Company~1" 或 "Great Company~1"
- 为什么 Elasticsearch 不将
Company~1作为同义词处理? - 关于如何使用 simpleQueryString 或 另一个 DSL 查询?
- 每个人都如何处理可能包含停用词的文本的模糊搜索?
[编辑] 我的分析器通常会删除的标点符号也会出现同样的问题。我不能在查询 b/c 中的模糊搜索字符串中包含任何标点符号,ES 分析器似乎没有将其视为非模糊的,并且我没有得到匹配结果。
基于上述搜索字符串的示例:Great Spaulding Company., 在我的代码中内置到短语 Great Spaulding~1 Company.,~1 并且 ES 不会删除标点符号或识别同义词 Company
我将尝试调用 ES _analyze REST api 的技巧,以便它告诉我应该在查询中包含哪些标记,尽管这会增加我构建的每个查询的开销。类似于http://localhost:9200/myEntity/_analyze?analyzer=vendorNameAnalyzer&text=Great Spaulding Company., 产生3 个令牌:great、spaulding 和company。
【问题讨论】:
标签: java elasticsearch lucene hibernate-search