0%

ElasticSearch-基于 Term-level 和 Full Text 查询

1. Term-level queries

相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/term-level-queries.html

Term 是表达语意的最小单位。搜索和利用统计语言模型进行自然处理都需要处理 Term,其具备如下特点:

  • Term Level Query 包含:Term Query / Range Query / Exists Query / Prefix Query / Wildcard Query
  • 在 ES 中,Term 查询对输入不做分词。会将输入作为一个整体,在倒排索引中查找准确的词项。且使用相关度算分公式会为每个包含该词项的文档进行相关度算分。
  • 可以通过 Constant Score 将查询转换成一个 Filtering,避免算分,并利用缓存,以提高性能

例如批量写入如下三个文档:

1
2
3
4
5
6
7
POST /products/_bulk
{ "index": { "_id": 1 }}
{ "productID" : "XHDK-A-1293-#fJ3","desc":"iPhone" }
{ "index": { "_id": 2 }}
{ "productID" : "KDKE-B-9947-#kL5","desc":"iPad" }
{ "index": { "_id": 3 }}
{ "productID" : "JODL-X-1937-#pV7","desc":"MBP" }

我们尝试使用 term 语句去检索索引的 desc 字段,可以发现当检索的词为 iPhone 时是无法检索出结果的,而检索的词为 iphone 时则可以检索出来。

1
2
3
4
5
6
7
8
POST /products/_search
{
"query": {
"term": {
"desc": "iPhone"
}
}
}

这是因为采用 term 语句检索时不会对检索的词 iPhone 进行分词处理,而此时倒排索引中存储的是 iphone(可以使用 _analyze 分析判断),故使用 iPhone 是无法检索到匹配的文档的。

同理对于 ProductID 我们也无法使用如下语句去找到匹配的文档,因为 XHDK-A-1293-#fJ3 在倒排索引中是做了分词处理的:

1
2
3
4
5
6
7
8
9
10
POST /products/_search
{
"query": {
"term": {
"productID": {
"value": "XHDK-A-1293-#fJ3"
}
}
}
}

我们可以使用 keyword 子字段进行精确匹配检索:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /products/_search
{
"query": {
"term": {
"productID.keyword": {
"value": "XHDK-A-1293-#fJ3"
}
}
}
}
// 响应(部分)
{
"_index" : "products",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.9808292,
"_source" : {
"productID" : "XHDK-A-1293-#fJ3",
"desc" : "iPhone"
}
}

可以看到能够正常获取到匹配值,需要注意的上面的查询 ES 实际参与了相关性算分,比如 _score 的值计算结果为 0.9808292。当然我们也可以将 Query 转成 Filter。一次忽略 TF-IDF 计算,避免相关性算分的开销,且 Filter 也可以有效的利用缓存。

1
2
3
4
5
6
7
8
9
10
11
12
POST /products/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"productID.keyword": "XHDK-A-1293-#fJ3"
}
}
}
}
}

2. Full text queries

相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/full-text-queries.html

ES 中的 Match Query、Match Phrase Query 和 Query String Query 都是基于全文本的查找,其具备如下特点:

  • 索引和搜索时都会进行分词,查询字符串先传递到一个合适的分词器,然后生成一个供查询的词项列表。
  • 查询时候,先会对输入的查询进行分词,然后每个词项逐个进行底层的查询,最终将结果进行合并。并为每个文档生成一个算分。例如查 “Matrix reloaded” 会查到包括 Matrix 或者 reload 的所有结果。

相关 Query 的使用我们已经在文章 ElasticSearch-SearchAPI 进行了介绍,这里不再赘述。

------ 本文结束------