elasticsearch 简单使用

1. 版本 信息

{
  "name" : "74c1872a9b2d",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "NtcKAJTdTd6rU-NTzwnrSg",
  "version" : {
    "number" : "8.1.0",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "3700f7679f7d95e36da0b43762189bab189bc53a",
    "build_date" : "2022-03-03T14:20:00.690422633Z",
    "build_snapshot" : false,
    "lucene_version" : "9.0.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

2. 字段属性

2.1. 常用属性

属性描述
type数据类型
index是否创建索引,默认 true
analyze分词器,对于中文一般选择 ik 分词器的:ik_smart 或 ik_max_word
format数据格式化,对于日期类型一般需要配置,可以配置多个,如 yyyy-MM-dd HH:mm:ss || yyyy-MM-dd
search_analyzer查询时使用的分词器,如果不配置默认使用 analyze 的配置项
properties嵌套的子字段

2.2. 数据类型

数据类型说明
字符串keyword:关键字类型,一般整体作为查询条件
text:文本类型,一般为一段文字,需要分词查询等
数字long、integer、short、byte、double、float、half_float、scaled_float
日期date,使用时一般配上 format 属性
日期纳秒date_nacos
布尔boolean
二进制binary
范围integer_range、float_range、long_range、double_range、date_range
经纬度geo_point,{lat:维度,lon: 经度} 其中:北纬为正数,南纬为负数,东经为正数,西经为负数
经纬范围geo_shape,由多个经纬度的点组合成的多边形
网络地址ip
数组es 中数组不需要一个特定的数据类型,任何字段都默认可以包含一个或多个值
嵌套对象object
嵌套数组nested

3. 分词器

3.1. 分词器组成结构

我们可以通过下面的三个部分组成自己想要的分词器效果

组成部分说明
Character Filter(字符过滤器)该部分负责对数据的预处理,比如去除特殊字符,转化图标为文字等
Tokenizer(分词器)该部分负责对一段文字进行分词,得到若干个词元
Token Filter(词元处理器)该部分负责对词元进一步加工,比如转化为拼音,首字母大写等等

3.2. 内置的分词器

分词器说明
standard去除绝大多数标点符号,英文按单词分割,中文按单个字分割,对中文词汇不是很友好
simple去除所有非字母字符,英文按标点与单词分割并转为小写,中文按标点分割
whitespace按空格切分,英文不转换大小写
stop类似于 simple 分词器,去除停用词(默认英文)
keyword不分词,原样返回
pattern正则分割,默认对所有非单词(非英文)字符分割 \w+
language语言分词器,未实现中文
fingerprint指纹算法分词器,对内容排序,并去重,最终只生成一个词条

3.3. 需要安装的常用分词器

分词器说明
ik_smart支持中文,粗粒度拆分
ik_max_word支持中文,最细粒度拆分
pinyin支持中文转拼音

3.4. 测试分词器

-- 非自定义分词器测试
GET /_analyze
{
  "analyzer": "my_analyzer",
  "text": "一段文本"
}

-- 自定义分词器的测试,需要指定索引名称,在哪个索引里配置的自定义分词器就用哪个索引
GET /索引名称/_analyze
{
  "analyzer": "my_analyzer",
  "text": "一段文本"
}

4. 索引操作

4.1. 创建索引

4.1.1. 分词器要求

  • 按照中文词语或者英文单词拆分文本
  • 中文汉字转化为拼音
  • 中文汉字转化为每个字的拼音首字母连接,如 拼音 -> py
PUT /study
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": "pinyin"
        }
      },
      "filter": {
        "pinyin": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "remove_duplicated_term": true,
          "limit_first_letter_length": 16,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {}
}

拼音分词器有很多配置项,大致如下

  • keep_first_letter:启用此选项时,例如:刘德华 > ldh,默认值:true
  • keep_separate_first_letter:启用此选项时,将单独保留首字母,例如:刘德华 > l,默认:false,注意:查询结果可能过于模糊
  • limit_first_letter_length:设置 first_letter 结果的最大长度,默认值:16
  • keep_full_pinyin:启用此选项时,例如:刘德华 > [ liu, de, hua],默认值:true
  • keep_joined_full_pinyin:启用此选项时,例如:刘德华 > [ liudehua],默认值:false
  • keep_none_chinese:结果中保留非中文字母或数字,默认值:true
  • keep_none_chinese_together:将非中文字母保持在一起,默认:true,例如:DJ音乐家 > DJyinyuejia
  • keep_none_chinese_in_first_letter:首字母保留非中文字母,例如:刘德华AT2016 > ldhat2016,默认:true
  • keep_none_chinese_in_joined_full_pinyin:保留非中文字母加入完整拼音,例如:刘德华2016 > liudehua2016,默认:false
  • none_chinese_pinyin_tokenize:如果是拼音,则将非中文字母分成单独的拼音词,默认:true,例如:liudehuaalibaba13zhuanghan > liu, de, hua, a, li, ba, ba, 13, zhuang, han, 注意:需要先启用 keep_none_chinese 和 keep_none_chinese_together
  • keep_original:启用此选项时,也将保留原始汉字,默认值:false
  • lowercase:非中文字母转小写,默认:true
  • trim_whitespace:去空格,默认真
  • remove_duplicated_term:删除重复的术语以保存索引,例如:de的 > de,默认:false,注意:位置相关的查询可能会受到影响
  • ignore_pinyin_offset:6.0以后,offset 被严格限制,tokens 重叠是不允许的,有了这个参数,tokens重叠会被忽略 offset,请注意,所有位置相关的查询或高亮都会变得不正确,你应该使用多个字段并为不同的设置指定不同的设置查询目的。如果需要偏移,请将其设置为 false。默认值:true。

4.1.2. 建一个索引

下方所有案例全部采用这个索引库:study

PUT /study
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "ik_max_word",
          "filter": ["length", "pinyin"]
        }
      },
      "filter": {
        "pinyin": {
          "type": "pinyin",
          "keep_full_pinyin": false,
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "remove_duplicated_term": true,
          "limit_first_letter_length": 16,
          "none_chinese_pinyin_tokenize": false
        },
        "length":{
          "type":"length",
          "min":2
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "id": {"type": "integer"},
      "name": {"type": "text", "analyzer": "my_analyzer", "search_analyzer": "ik_max_word"},
      "birthday": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"},
      "weight": {"type": "double"},
      "describe": {"type": "text", "analyzer": "my_analyzer", "search_analyzer": "ik_max_word"}
    }
  }
}

4.2. 删除索引

DELETE /study

4.3. 修改索引

  • ES 不允许修改或者删除已经存在的字段
  • 修改索引准确的来讲相当于新增字段
PUT /study/_mapping
{
  "properties": {
    "geo" : {"type": "geo_point"}
  }
}

4.4. 查询索引

4.4.1. 查看全部索引

GET /_cat/indices

-- 返回值
yellow open study aK2MakZXTp-y0ezGOadPiw 1 1 0 0 225b 225b

-- 返回值每一列的意思:
yellow:健康状态,yellow 警告,green 健康,单节点部署的话都为 yellow
open:  当前索引是 打开或关闭 状态
study: 索引名称
aK2MakZXTp-y0ezGOadPiw:索引的唯一标识
1:主分片数
1:副本分片数
0:可用文档
0:已删除文档
225b:主分片、副本分片总存储大小
225b:主分片存储大小

4.4.2. 查询具体索引

GET /study

5. 文档操作

5.1. 新增/覆盖 文档

  • 下方命令中结尾的 2 为文档唯一 ID,字符串类型,如果不设置在会自动生成
  • 如果在执行下方的命令时,发现 ID 已经存在,则会覆盖原来的数据,起到全量修改的作用
POST /study/_doc/2
{
  "id": 2,
  "name": "李四",
  "birthday": "1992-07-16 00:00:00",
  "weight": 90.20,
  "describe": "这是一个品学兼优的学生",
  "sex": "男",
  "geo": "30,60"
}

5.2. 删除文档

  • 下方命令中结尾的 1 为文档新增时设置的唯一 ID
DELETE /study/_doc/1

5.3. 修改文档

  • 如果需要修改大量字段,推荐采用 新增,覆盖的方式
  • 如果只是局部修改一两个字段,可以采用下方的命令
  • 下方命令中结尾的 2 为文档新增时设置的唯一 ID
POST /study/_update/2
{
  "doc": {
    "sex": "女"
  }
}

5.4. 查询文档

  • 下方命令中结尾的 2 为文档新增时设置的唯一 ID
GET /study/_doc/2

6. 条件查询

  • 上方已经实现了根据唯一 ID 的简单查询,但是数据的查询往往不可能这么简单,下方介绍一些常用的查询方式

6.1. 一些关键参数

{
    "query": { 具体的 DSL 查询条件 },
    "from": "数字:分页的起始位置,默认 0",
    "size": "数字:每页的最大显示条数,默认 10",
    "sort": [{"字段": "升序 asc、降序 desc"}]
}
  • from 和 size 类似于 mysql 中 limit 查询的两个参数
  • size 最大值不能超过 10000
  • es 的查询不存在全量,都存在分页约束

6.2. 查询全部

  • 查询方式:match_all

  • 由于 ES 的查询都被分页约束,所以该查询相当于没有任何条件的分页查询

  • 想要多看见几条数据,可以加 from:0,size:10000 查看最多一万条数据(不推荐)

GET /study/_search
{
  "query": {"match_all": {}}
}

6.3. 模糊查询

  • 查询方式:match 和 multi_match
  • 该种方式的查询字段仅适用于:text 类型的数据
-- 单字段
GET /study/_search
{
  "query": {
    "match": {
      "name": "ZS"
    }
  }
}

-- 多字段
GET /study/_search
{
  "query": {
    "multi_match": {
      "query": "调皮捣蛋",
      "fields": ["describe", "name"]
    }
  }
}

6.4. 精确查询

精确查询不支持 text 类型的字段

6.4.1. 相等查询

  • 查询方式:term
  • 类似于传统数据库的 (where field = value)
GET /study/_search
{
  "query": {
    "term": {"sex": "男"}
  }
}

6.4.2. 范围查询

6.4.2.1. 常规范围查询
  • 查询方式:range
  • 适用数据类型:数字,keyword,date 等
  • 类似于传统数据库的 (where field > value1 and field < field2 或者 between … and)
  • gt、gte:大于 大于等于
  • le、lte: 小于 大于等于
GET /study/_search
{
  "query": {
    "range": {
      "weight": {"gte": 10, "lte": 200}
    }
  }
}
6.4.2.2. 经纬度范围查询
  • 查询方式:geo_bounding_box
  • 适用数据类型:geo_point
  • top_left:左上角的点坐标
  • bottom_right:右下角的点坐标
  • 查询逻辑:两个点拉成一个矩形,在矩形范围内的点都会被查询出来
  • 以下为 西经50度到东京100度,北纬10度到北纬30度 范围内的数据
GET /study/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": { "lat": 30, "lon": -50 },
        "bottom_right": { "lat": 10, "lon": 100 }
      }
    }
  }
}
6.4.2.3. 经纬度距离查询
  • 查询方式:geo_distance
  • 适用数据类型:geo_point
  • distance:距离
  • location:一个坐标,维度,经度
  • 查询逻辑:计算两个坐标之间的距离,获取 distance 指定范围内的数据
  • 以下为 查询距离 东经59度北纬30度150公里 范围内的数据
GET /study/_search
{
  "query": {
    "geo_distance": {
      "distance": "150km",
      "location": "30,59"
    }
  }
}

6.5. 算分排序

6.5.1. 算分规则

ES 在未指定排序字段时,默认会给每一条文档进行打分(_score),分数越高的文档,在查询结果中的排序越靠前。再次基础上,我们可以通过算分函数(function_score)人为干预算分结果,从而实现我们想要的排序结果。如:通过 钞能力 让自己的搜索结果比较靠前

干预算分的三个条件

  • filter:过滤条件,只对满足条件的文档做算分干预,比如充过钱的

  • 算分函数包括:

    • weight:一个常量
    • field_value_factor:用某个字段代替算分,必须是数字类型的字段
    • random_score:随机数
    • script_score:自定义计算公式
  • boost_mode:两种算分模式计算后的 运算模式

    • multiply:query_score + function_score
    • replace: function_score 替换 query_score
    • sum(相加),avg(取平均),max(取最大),min(取最小) 等

6.5.2. 一个例子

  • 查询方式:function_score
  • 以下为查询时,给 王五 的算分在默认的基础上加上 20 分,让他排在第一
GET /study/_search
{
  "query": {
    "function_score": {
      "query": {"match_all": {}},
      "functions": [
        {
          "filter": {"match" : { "name": "王五"} },
          "weight": 20
        }
      ],
      "boost_mode": "sum"
    }
  }
}

6.6. 组合查询

6.6.1. 四个组成部分

  • must:必须匹配,其中的内容必须全部符合,相当于 与
  • should:选择性匹配,其中的内容只需要匹配一个,相当于 或
  • must_not:必须不匹配,不参与算分,其中内容必须完全不匹配,相当于 非
  • filter:必须匹配,不参与算分,其中的内容必须全部符合,相当于 与
  • PS:当 must 和 should 同时存在是,should 不起作用,只会增加算分

正常情况下,不参与算分的字段尽量放到 must_not 和 filter 从而提高性能

6.6.2. 一个例子

  • 查询方式:bool

  • 以下为查询:描述中包含学生,且 id 等于2 的数据

GET /study/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": { "describe": "学生" }}, 
        {"term": { "id": 2 }}
      ]
    }
  }
}

6.7. 排序

6.7.1. 常规排序

  • 排序方式: sort
  • 以下为根据 id 倒序
GET /study/_search
{
  "query": {"match_all": {}},
  "sort": [
    {"id": "desc"}
  ]
}

6.7.2. 坐标距离排序

  • 排序方式:_geo_distance
  • 一下为距离当前位置由近到远,并计算出距离
GET /study/_search
{
  "query": {"match_all": {}},
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 40,
          "lon": -70
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

6.8. 关键字高亮

  • 高亮方法:highlight
  • pre_tags:前缀,默认
  • post_tags:后缀,默认
  • require_field_match:高亮字段是否和原字段要一致,默认 true
GET /study/_search
{
  "query": {"match": {
    "describe": "一个学生"
  }},
  "highlight": {
    "fields": {
      "describe": {
        "pre_tags": "<em>",
        "post_tags": "</em>",
        "require_field_match": "false"
      }
    }
  }
}

7. 初始化脚本

POST /study/_doc/1
{
  "id": 1,
  "name": "张三",
  "birthday": "1991-07-16 00:00:00",
  "weight": 45.32,
  "describe": "这是一个调皮捣蛋的学生",
  "sex": "女",
  "location": "30,-45"
}

POST /study/_doc/2
{
  "id": 2,
  "name": "李四",
  "birthday": "1992-07-16 00:00:00",
  "weight": 90.20,
  "describe": "这是一个品学兼优的学生",
  "sex": "男",
  "location": "30,60"
}

POST /study/_doc/3
{
  "id": 3,
  "name": "王五",
  "birthday": "2020-07-16 00:00:00",
  "weight": 120.32,
  "describe": "这是一个中规中矩的学生",
  "sex": "男",
  "location": "30,-45"
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值