【搜索技术】ElasticSearch进阶实践

目录

  • ElasticSearch 进阶

    • SearchAPI

      • 检索信息

    • Query DSL

      • 基本语法格式
      • 查询-match
      • 查询-match_phrase
      • 查询-multi_match
      • 查询-bool复合查询
      • 查询-filter过滤
      • 查询-term
      • Aggregations

    • Mapping

      • 查看索引
      • 创建索引
      • 添加新字段映射
      • 更新映射
      • 数据迁移

    • 分词

      • 安装IK分词器
      • 测试IK分词器
      • 自定义词库

ElasticSearch 进阶

SearchAPI

ES 支持两种基本方式检索 :

  • 一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
  • 一个是通过使用 REST request body 来发送它们(uri+请求体)

检索信息

请求参数详情
GET bank/_search检索 bank 下所有信息,包括 type 和 docs
GET bank/_search?q=*&sort=account_number:asc请求参数方式检索

响应结果解释:

took - Elasticsearch 执行搜索的时间(毫秒)

time_out - 告诉我们搜索是否超时

_shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片

hits - 搜索结果

hits.total - 搜索结果

hits.hits - 实际的搜索结果数组(默认为前 10 的文档)

sort - 结果的排序 key(键)(没有则按 score 排序)

score 和 max_score –相关性得分和最高得分(全文检索用)

  • uri+请求体

# GET查询 kibana查询

GET bank/_search

{

"query": {

"match_all": {}

},

"sort": [

{

"account_number": "asc"

},

{

"balance": "desc"

}

]

}

HTTP 客户端工具(POSTMAN),get 请求不能携带请求体,我们变为 post 也是一样的我们 POST 一个 JSON 风格的查询请求体到 _search API。

需要了解,一旦搜索的结果被返回,Elasticsearch 就完成了这次请求,并且不会维护任何

服务端的资源或者结果的 cursor(游标)

Query DSL

基本语法格式

Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSL(domain-specific language 领域特定语言)。这个被称为Query DSL。该查询语言非常全面,并且刚开始的时候感觉有点复杂, 学好它的方法是从一些基础的示例开始的。

# 查询语句

{

QUERY_NAME: {

ARGUMENT: VALUE,

ARGUMENT: VALUE,

...

}

}

# 查询语句-针对某个字段

{

QUERY_NAME: {

FIELD_NAME: {

ARGUMENT: VALUE,

ARGUMENT: VALUE,

...

}

}

}

查询-match

# kibana查询

GET bank/_search

{

"query": {

"match_all": {}

},

"from": 0,

"size": 5,

"sort": [

{

"account_number": {

"order": "desc"

}

}

]

}

query :定义查询

match_all 查询类型: 代表查询所有的所有

from+size 限定: 分页功能

sort : 排序

# kibana查询-返回部分字段

GET bank/_search

{

"query": {

"match_all": {}

},

"from": 0,

"size": 5,

"_source": ["age","balance"]

}

# kibana查询-match查询

基本类型(非字符串),精确匹配;match 返回 account_number=20 的数据

GET bank/_search

{

"query": {

"match": {

"account_number": "20"

}

}

}

# kibana查询-字符串查询

最终查询出 address 中包含 mill 单词的所有记录

GET bank/_search

{

"query": {

"match": {

"address": "mill"

}

}

}

注: match 当搜索字符串类型的时候,会进行全文检索,并且每条记录有相关性得分。

# 字符串,多个单词(分词+全文检索)

查询-match_phrase

不分词匹配

# 查出 address 中包含 mill road 的所有记录,并给出相关性得分

GET bank/_search

{

"query": {

"match_phrase": {

"address": "mill road"

}

}

}

查询-multi_match

多字段匹配

# state 或 address 包含 mill 或 movico

GET bank/_search

{

"query": {

"multi_match": {

"query": "mill Movico",

"fields": ["state","address"]

}

}

}

查询-bool复合查询

bool 用来做复合查询:

复合语句可以合并任何它查询语句,包括复合语句,了解这一点是很重要的。

复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

# 查询address必须为mill age必须为28 lastname可为helloand也可不为helloand的数据

# must:必须达到 must 列举的所有条件

# must_not 必须不是指定的情况

# should:应该达到 should 列举的条件,如果达到会增加相关文档的评分,并不会改变查询的结果。

GET bank/_search

{

"query": {

"bool": {

"must": [

{

"match": {

"address": "mill"

}

},

{

"match": {

"gender": "M"

}

}

],

"must_not": [

{"match": {

"age": "28"

}}

],

"should": [

{

"match": {

"lastname": "Holland"

}

}

]

}

}

}

查询-filter过滤

并不是所有的查询都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。为了不计算分数 Elasticsearch 会自动检查场景并且优化查询的执行。

GET bank/_search

{

"query": {

"bool": {

"must": [

{

"range": {

"age": {

"gte": 18,

"lte": 30

}

}

},

{

"match": {

"address": "mill"

}

}

]

}

}

}

GET bank/_search

{

"query": {

"bool": {

"filter": [

{

"range": {

"age": {

"gte": 18,

"lte": 30

}

}

}

]

}

}

}

查询-term

和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。

ElasticSearch 进阶

# 检索时 非text字段则使用term

GET bank/_search

{

"query": {

"term": {

"balance": "32838"

}

}

}

GET bank/_search

{

"query": {

"match": {

"balance": "32838"

}

}

}

Aggregations

Aggregations结构:

"aggregations" : {

"<aggregation_name>" : {

"<aggregation_type>" : {

<aggregation_body>

}

[,"meta" : { [<meta_data_body>] } ]?

[,"aggregations" : { [<sub_aggregation>]+ } ]?

}

[,"<aggregation_name_2>" : { ... } ]*

}

Aggregations范例:

# 搜索 address 中包含mill的所有人的年龄分布以及平均年龄,但不显示这些人的详情

GET bank/_search

{

"query": {

"match": {

"address": "mill"

}

},

"aggs": {

"ageAgg": {

"terms": {

"field": "age",

"size": 10

}

},

"ageAvg":{

"avg":{

"field":"age"

}

},

"balanceAvg":{

"avg": {

"field": "balance"

}

}

},

"size": 0

}

# 按照年龄聚合,并且请求这些年龄段的这些人的平均薪资

GET bank/_search

{

"query": {

"match_all": {}

},

"aggs": {

"ageAgg": {

"terms": {

"field": "age",

"size": 100

},

"aggs": {

"ageAvg": {

"avg": {

"field": "balance"

}

}

}

}

}

}

# 查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资

GET bank/_search

{

"query": {

"match_all": {}

},

"aggs": {

"ageAgg": {

"terms": {

"field": "age",

"size": 100

},

"aggs": {

"genderAgg": {

"terms": {

"field": "gender.keyword",

"size": 10

},

"aggs": {

"balanceAvg": {

"avg": {

"field": "balance"

}

}

}

},

"ageBalanceAvg":{

"avg": {

"field": "balance"

}

}

}

}

}

}

Mapping

Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。

查看索引

# 查看 mapping 信息 kibana dev Tools执行

GET bank/_mapping

创建索引

创建索引-创建索引并指定映射

PUT /my_index

{

"mappings": {

"properties": {

"age": {"type": "integer"},

"email": {"type": "keyword"},

"name": {"type": "text"}

}

}

}

添加新字段映射

# 添加新字段映射

PUT /my_index/_mapping

{

"properties":{

"employee_id":{

"type":"keyword",

"index":false

}

}

}

更新映射

ElasticSearch 进阶

对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移

# 查看存在映射

GET /my_index/_mapping

GET /bank/_search

# 更新索引映射

PUT /newbank

{

"mappings": {

"properties": {

"account_number": {

"type": "long"

},

"address": {

"type": "text"

},

"age": {

"type": "integer"

},

"balance": {

"type": "long"

},

"city": {

"type": "keyword"

},

"email": {

"type": "keyword"

},

"employer": {

"type": "keyword"

},

"firstname": {

"type": "text"

},

"gender": {

"type": "keyword"

},

"lastname": {

"type": "text",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

}

},

"state": {

"type": "keyword"

}

}

}

}

# 获取新索引

GET /newbank/_mapping

数据迁移

先创建出 new_twitter的正确映射。

数据迁移格式:

# elasticsearch 新版本数据迁移

POST _reindex [固定写法]

{

"source": {

"index": "twitter"

},

"dest": {

"index": "new_twitter"

}

}

# elasticsearch 老版本数据迁移

# 旧索引的 type 下的数据进行迁移

POST _reindex

{

"source": {

"index": "twitter",

"type": "tweet"

},

"dest": {

"index": "tweets"

}

}

数据迁移:

# 查看存在映射

GET /my_index/_mapping

GET /bank/_search

# 更新索引映射

PUT /newbank

{

"mappings": {

"properties": {

"account_number": {

"type": "long"

},

"address": {

"type": "text"

},

"age": {

"type": "integer"

},

"balance": {

"type": "long"

},

"city": {

"type": "keyword"

},

"email": {

"type": "keyword"

},

"employer": {

"type": "keyword"

},

"firstname": {

"type": "text"

},

"gender": {

"type": "keyword"

},

"lastname": {

"type": "text",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

}

},

"state": {

"type": "keyword"

}

}

}

}

GET /newbank/_mapping

# 数据迁移 老版本迁移

POST _reindex

{

"source": {

"index": "bank",

"type": "account"

},

"dest": {

"index": "newbank"

}

}

GET /newbank/_search

# 不用type 老数据可以迁移过来

分词

一个 tokenizer(分词器)接收一个字符流,将之分割为独立的 tokens(词元,通常是独立的单词),然后输出 tokens 流。

例如,whitespace tokenizer 遇到空白字符时分割文本。它会将文本 "Quick brown fox!" 分割为[Quick, brown, fox!]。

该 tokenizer(分词器)还负责记录各个 term(词条)的顺序或 position 位置(用于 phrase 短语和 word proximity 词近邻查询),以及 term(词条)所代表的原始 word(单词)的 start

(起始)和 end(结束)的 character offsets(字符偏移量)(用于高亮显示搜索的内容)。Elasticsearch 提供了很多内置的分词器,可以用来构建custom analyzers(自定义分词器)。

# 支持英文分词器 对中文的分词不友好

POST _analyze

{

"analyzer": "standard",

"text": "The 2 QUICK Brown-Foxes jumped over the lazy dog's bone."

}

安装IK分词器

IK分词器下载-点我传送

# wget下载 /mydata/elasticsearch/plugin

$ wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

# 进入docker容器

$ docker exec -it elasticsearch /bin/bash

$ cd /bin/

$ elasticsearch-plugin

$ elasticsearch-plugin -h

# 列出系统的分词器

$ elasticsearch-plugin list

# 重启容器

$ docker restart elasticsearch

测试IK分词器

# ik分词器

POST _analyze

{

"analyzer": "ik_max_word",

"text": "我是中国人"

}

# ik分词器

POST _analyze

{

"analyzer": "ik_smart",

"text": "我是中国人"

}

自定义词库

修改/mydata/elasticsearch/plugins/elasticsearch-analysis-ik-7.4.2/config中的 IKAnalyzer.cfg.xml

# IKAnalyzer.cfg.xml 配置文件内容

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>

<comment>IK Analyzer 扩展配置</comment>

<!--用户可以在这里配置自己的扩展字典 -->

<entry key="ext_dict"></entry>

<!--用户可以在这里配置自己的扩展停止词字典-->

<entry key="ext_stopwords"></entry>

<!--用户可以在这里配置远程扩展字典 -->

<!-- <entry key="remote_ext_dict">words_location</entry> -->

<!--用户可以在这里配置远程扩展停止词字典-->

<!-- <entry key="remote_ext_stopwords">words_location</entry> -->

</properties>

添加自定义词库:

# 获取 自定义词库的地址 一般是安装在nginx上

http://192.168.188.128/es/fenci.txt

# IK config配置

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>

<comment>IK Analyzer 扩展配置</comment>

<!--用户可以在这里配置自己的扩展字典 -->

<entry key="ext_dict"></entry>

<!--用户可以在这里配置自己的扩展停止词字典-->

<entry key="ext_stopwords"></entry>

<!--用户可以在这里配置远程扩展字典 -->

<entry key="remote_ext_dict">http://192.168.188.128/es/fenci.txt</entry>

<!--用户可以在这里配置远程扩展停止词字典-->

<!-- <entry key="remote_ext_stopwords">words_location</entry> -->

</properties>

# 重启elasticsearch、nginx

$ docker restart elasticsearch

$ docker restart nginx

以上是 【搜索技术】ElasticSearch进阶实践 的全部内容, 来源链接: utcz.com/a/120757.html

回到顶部