前言:全文检索是Elasticsearch提供的强大搜索引擎功能。可以实现对文本数据进行全面的搜索和匹配。全文检索是通过将查询词与文档中的文本内容进行匹配来实现的。
全文检索涉及的主要概念
分词器(Tokenizer)
Elasticsearch使用分词器将文本分割成单词或词条。默认情况下Elasticsearch 使用标准分词器(Standard Tokenizer),但还提供了其他各种分词器,例如:IK分词器,hanlp分词器,拼音分词器,QQ分词器,keyword分词器等。分词器会将客户端写入的文本数据通过分词算法结合分词词典,将文本数据拆分成有意义的词汇单元(也称为词项),以便进行索引和搜索。
倒排索引(Inverted Index)
Elasticsearch使用倒排索引来加速文本搜索。倒排索引将每个词条映射到包含该词条的文档列表。这样,当执行搜索时,可以快速找到包含查询词的文档。倒排索引的使用使得 Elasticsearch 能够高效地进行全文搜索。
查询 DSL(Domain-Specific Language)
Elasticsearch提供了丰富的查询 DSL,用于构建各种复杂的查询。我们可以使用诸如匹配查询、短语查询、范围查询、布尔查询等多种查询类型来满足不同的搜索需求。查询DSL提供了灵活的搜索语法和参数,使用户能够精确地定义搜索条件。
相似度评分(Similarity Scoring)
Elasticsearch 使用相似度评分算法来计算查询与文档的匹配程度。默认情况下,Elasticsearch使用TF-IDF(Term Frequency-Inverse Document Frequency)算法进行相似度评分。相似度评分决定了搜索结果的排序和相关性。
Full text queries(全文检索)
intervals query(区间查询)
使用匹配规则对数据进行查询。使用该语法我们可以自己在查询语句中定义匹配模式,使用不同的操作符来定义查询区间的条件。
在以下查询样例中,我们使用match操作符,用来匹配"my favorite food",指定最大间隔数为0,同时使用any_of来设置子查询条件。在当前样例中any_of包含了两个子查询条件。子查询条件的含义为使用match匹配"在很冷的情况下,我喜欢的食物是热粥"的数据。
代码语言:json复制POST _search
{
"query": {
"intervals" : {
"my_text" : {
"all_of" : {
"ordered" : true,
"intervals" : [
{
"match" : {
"query" : "my favorite food",
"max_gaps" : 0,
"ordered" : true
}
},
{
"any_of" : {
"intervals" : [
{ "match" : { "query" : "hot water" } },
{ "match" : { "query" : "cold porridge" } }
]
}
}
]
}
}
}
}
}
在intervals query中还支持以下匹配方式:
prefix
匹配规则:用于匹配以指定前缀开头的词条。
{
"intervals": {
"field": {
"prefix": "pre"
}
}
}
wildcard
匹配规则:用于匹配符合通配符模式的词条
{
"intervals": {
"field": {
"wildcard": "te*"
}
}
}
fuzzy
匹配规则:用于匹配与指定词条相似的词条
{
"intervals": {
"field": {
"fuzzy": {
"term": "text",
"fuzziness": 2
}
}
}
}
Match Query
使用Match语句进行文本查询时,如果我们没有指定查询时的分词器,或我们要进行匹配的字段没有指定特定的分词器,则Match请求在执行时,就会使用默认分词器对文本进行解析。然后返回匹配到的文档,内容可以为匹配到的文本,日期,布尔值等信息。
其用法为:
在这个请求中,我们对message字段进行全文检索,默认分词器会对"this is a test"进行分词,然后进行匹配。
代码语言:javascript复制GET /_search
{
"query": {
"match": {
"message": {
"query": "this is a test"
}
}
}
}
常用参数
analyzer:用于对传入的数据进行分词拆分,默认为字段映射时的分词器。如果没有指定,则默认使用索引中指定的分词器。
fuzziness:用于设置Match查询中的模糊相关性,该参数用于约束是否开启精确模糊匹配。
Match boolean prefix query
布尔前缀匹配查询。可以在文本的任何位置匹配需要搜索的关键字。其与bool查询最大的区别在于bool查询执行在特定的位置进行关键字的匹配。而Match boolean prefix query可以在任何位置进行匹配。此外在Match boolean prefix query还支持运算符参数。
用法如下:
代码语言:javascript复制GET /_search
{
"query": {
"match_bool_prefix" : {
"message" : "quick brown f"
}
}
}
其功能类似于精确查询中的bool查询
代码语言:javascript复制GET /_search
{
"query": {
"bool" : {
"should": [
{ "term": { "message": "quick" }},
{ "term": { "message": "brown" }},
{ "prefix": { "message": "f"}}
]
}
}
}
Match phrase query
短语匹配查询。短语匹配查询一般需要结合分词器进行使用。分词器会将我们传入的关键字切分为若干个短语。
代码语言:javascript复制GET /_search
{
"query": {
"match_phrase": {
"message": {
"query": "this is a test",
"analyzer": "my_analyzer"
}
}
}
}
我们可以通过设置slop参数来决定在匹配短语时,允许词项间的最大间隔数。加大的slop值允许更大的间隔数,较小的slop值则会让各词项间的间隔更紧密。以此来限制匹配的灵活性。
使用样例如下:
代码语言:javascript复制{
"query": {
"match_phrase": {
"field": {
"query": "example phrase",
"slop": 2
}
}
}
}
Match phrase prefix query
短语前缀匹配查询。将传入的关键字切分为短语进行前缀匹配。搜索关键字中的最后一个短语,匹配以该短语开头的任何关键字。
用法如下:
代码语言:javascript复制GET /_search
{
"query": {
"match_phrase_prefix": {
"message": {
"query": "quick brown f"
}
}
}
}
Multi-match query
多字段匹配查询。我们使用match查询时,指定匹配单个字段,当我们需要对多个字段进行匹配时,则可以通过Multi-match query进行全文检索。如果我们在查询语句中没有对"fields"进行设置,则查询在执行时就会默认将"fields"设置为*,然后对所有字段进行匹配。
用法如下:
代码语言:javascript复制GET /_search
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
我们可以通过设置type字段来决定使用哪种方式对多字段进行匹配。
其用法如下:
代码语言:javascript复制GET /_search
{
"query": {
"multi_match" : {
"query": "brown fox",
"type": "best_fields",
"fields": [ "subject", "message" ],
"tie_breaker": 0.3
}
}
}
#上述查询将会被解析为:
GET /_search
{
"query": {
"dis_max": {
"queries": [
{ "match": { "subject": "brown fox" }},
{ "match": { "message": "brown fox" }}
],
"tie_breaker": 0.3
}
}
}
type支持的类型
best_fields:默认查找任何字段与关键字匹配的文档,然后使用评分(_score)最佳的字段结果进行返回。
most_fields:查找全部字段匹配的文档。然后在结果中取绝大部分符合评分(_score)要求的字段。
cross_fields:使用相同的分词器处理这些字段,将这些字段作为一个大的字段进行解析处理。
phrase:对每个字段进行短语匹配查询,然后使用评分(_score)最佳的字段。
phrase_prefix:对每个字段进行短语前缀匹配,然后使用评分(_score)最佳的字段。
bool_prefix:在每个字段上进行布尔前缀匹配。并综合每个字段的评分(_score)。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!