elasticsearch查询之全文检索

2023-11-23 17:07:48 浏览数 (2)

前言:全文检索是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匹配规则:用于匹配以指定前缀开头的词条。

代码语言:javascript复制
{
     "intervals": {
       "field": {
         "prefix": "pre"
       }
     }
   }

wildcard匹配规则:用于匹配符合通配符模式的词条

代码语言:javascript复制
{
     "intervals": {
       "field": {
         "wildcard": "te*"
       }
     }
   }

fuzzy匹配规则:用于匹配与指定词条相似的词条

代码语言:javascript复制
{
     "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腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞