ES的基本操作
我正在参加「掘金·启航计划」
本次操作将在 Kiana中进行
当然你也可以在 PostMan 或者浏览器搜索框 等等能发送请求的地方进行
1. 测试分词器
1.1 测试 IK 分词器
使用 Kianan的控制台进行测试
GET _analyze
{
"analyzer": "ik_smart",
"text": "Redis中国网站" #要切分的文本
}
GET _analyze
{
"analyzer": "ik_max_word", # 最细粒度切分 穷尽词库的可能!字典!
"text": "Redis中国网站" # 要切分的文本
}
IK 添加自定义词语
通过以上测试结果可以看到 不管是哪种切分方式 都会根据你的词库来进行切分
- ik_smart 最粗粒度切分
- ik_max_word 最细粒度切分
1.2 测试 pinyin 分词器
- 测试步骤与 ik 一致
GET _analyze
{
"analyzer": "pinyin",
"text": ["中国"]
}
返回结果
可以看到 拆分结果为 每个汉字的全拼拼音 和 每个汉字的首字母 所以结果就是
- zhong : 中
- zg 中国
- guo 国
{
"tokens" : [
{
"token" : "zhong",
"start_offset" : 0,
"end_offset" : 0,
"type" : "word",
"position" : 0
},
{
"token" : "zg",
"start_offset" : 0,
"end_offset" : 0,
"type" : "word",
"position" : 0
},
{
"token" : "guo",
"start_offset" : 0,
"end_offset" : 0,
"type" : "word",
"position" : 1
}
]
}
2. 关于索引的基本操作
1.1创建索引
- 创建索引
PUT /索引名称
- 创建索引同时设置索引的参数
- 分片数
- 副本数 等配置
PUT /sc
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
}
}
该种方式为自动创建索引 而且数据也添加成功了
那么为什么不用给字段指定名称呢?
elasticsearch会自动的将新字段加入映射,但是这 个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18,那么elasticsearch会认为它 是整形。 但是elasticsearch也可能猜不对, 所以最安全的方式就是提前定义好所需要的映射,这点跟关 系型数据库殊途同归了,先定义好字段,然后再使用,别 整什么幺蛾子。
1.2 指定字段的类型创建索引
PUT /shop
{
"mappings": {
"goods": {
"properties": {
"name": {
"type": "text"
},
"price": {
"type": "double"
},
"sjDate": {
"type": "date"
}
}
}
}
}
1.3 获取索引信息
- 获取单个
GET /yufire # 使用GET请求 直接请求要查询的索引
- 获取所有 方式一
GET _cat/indices?v
- 方式二
GET /_all
1.4 添加索引映射信息
- 一旦映射信息固定 就不可以进行修改了
- 只能进行添加映射操作
POST /shop/_mapping/goods
{
"properties": {
"age": {
"type": "integer"
}
}
}
1.5 删除索引
- 删除单个索引
DELETE /yufire
- 删除全部索引
DELETE _all
1.6 自定义分词器
- 可以再一个属性映射上同时添加多个分词器
1. 首先创建一个索引
ik_smart_pinyin 为我们自定义分词器的名称
ik_smart_pinyin 中包含了 ik 和 pinyin 分词器
PUT /IndexName
{
"settings": {
"analysis": {
"analyzer": {
"ik_smart_pinyin": {
"type": "custom",
"tokenizer": "ik_smart",
"filter": ["my_pinyin", "word_delimiter"]
},
"ik_max_word_pinyin": {
"type": "custom",
"tokenizer": "ik_max_word",
"filter": ["my_pinyin", "word_delimiter"]
}
},
"filter": {
"my_pinyin": {
"type" : "pinyin",
"keep_separate_first_letter" : true,
"keep_full_pinyin" : true,
"keep_original" : true,
"limit_first_letter_length" : 16,
"lowercase" : true,
"remove_duplicated_term" : true
}
}
}
}
}
2. 重新指定文档类型映射拼音分词类型
- name 只是作为一个示范 其他的映射自行添加
- 把name属性的analyzer 和 search_analyzer 设置为 我们自定义的 ik_smart_pinyin 分词器即可
POST /goods/_mapping/
{
"properties": {
"name": {
"type": "text",
"analyzer":"ik_smart_pinyin",
"search_analyzer":"ik_smart_pinyin"
}
}
}
3. 文档操作 重点
基本操作
2.1 创建文档
创建文档操作等于向MySQL中添加数据
PUT /yufire/user/1
{
"name":"yufire",
"age":3
}
- 可以不指定id 会自动生成一个字符串作为id
- 如果创建索引的时候没有指定类型的话 默认类型为 _doc
- 第一次创建文档的时候 result状态为 created
2.2 获取数据
GET /yufire/_doc/1
2.3 修改数据
2.3.1 PUT方式修改
- 这种方式就是 使用PUT 请求 直接将源数据给覆盖掉 官方并不推荐这种方法
- 如果修改的参数和mapping映射不一样的话 数据会出现错乱问题
PUT /yufire/_doc/1
{
"name":"yufire2",
"age":3,
"birthday":"2020-04-21"
}
2.3.2 POST方式修改
- POST _update , 官方推荐使用这种更新方式!
POST /yufire/_doc/1/_update
{
"doc":{
"name":"yufire3"
}
}
2.4 简单的搜索
现在索引库中有 5 条数据
GET /yufire/_doc/_search?q=name:yufire1
# 使用GET请求做一个简单的搜索
2.5 复杂的查询 重点
2.5.1 mathc 查询
- 相当于 like
match query 知道分词器的存在 他会根据分词器进行拆分
如果查询的数据没有在分词器中配置的话 那么就会进行精确查询
分词器中配置了该词的结果
分词器中没有配置该词的结果
GET /yufire/_doc/_search
{
"query":{
"match":{
"name":"中国中央电视"
}
}
}
2.5.2 结果过滤
- 在 query节点后边加上_source 输入过滤字段 即可
GET /yufire/_doc/_search
{
"query":{
"match":{
"name":"yufire1"
}
},
"_source":["name","age"]
}
2.5.3 排序
- 在 query节点后边添加 sort 节点
GET /yufire/_doc/_search
{
"query":{
"match":{
"name":"中央"
}
},
"_source":["age"],
"sort":{
"age":{
"order":"asc"
}
}
}
# order 的值 根MySQL中对应 asc为升序 desc为降序
2.5.4 分页查询
- 分页查询与mysql中类似 只需要两个参数即可
- from : 对应MySQL中的 limit 第一个参数
- size : 对应MySQL中的 limit 第二个参数
- limit from,size
GET /yufire/_doc/_search
{
"query":{
"match":{
"name":"中央"
}
},
"_source":["age"],
"sort":{
"age":{
"order":"asc"
}
},
"from":0,
"size":2
}
# limit from,size
2.5.5 布尔值查询 and
-
多条件查询
-
must (and),所有的条件都要符合 where name=xxx1 and age= xxx
GET /yufire/_doc/_search
{
"query": {
"bool": {
"must": [ # 存放条件的数组
{ # 一个个的条件对象
"match": {
"name": "中央电视台"
}
},
{ # 一个个的条件对象
"match": {
"age": 17
}
}
]
}
}
}
2.5.6 布尔值查询 or
- should 关键字 就等于mysql中的 or
- should (or) where name=xxx or age=xxx
GET /yufire/_doc/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "中央电视台"
}
},
{
"match": {
"age": 17
}
}
]
}
}
}
2.5.7 布尔值查询 not
- must_not 就相当于mysql中的 not
GET /yufire/_doc/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 17
}
}
]
}
}
}
2.5.8 过滤器 filter
-
可以使用 filter进行数据的过滤
-
gt 大于
-
gte 大于等于
-
lt 小于
-
lte 小于等于!
GET /yufire/_doc/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 17
}
}
],
"filter": {
"range": {
"age": {
"gte": 1,
"lte": 3
}
}
}
}
}
}
2.5.9 匹配数组
- 如果文档中的数据有数组的话 可以直接用match关键字进行匹配
GET /yufire/_doc/_search
{
"query":{
"match":{
"tags":"唱 跳 rap"
}
}
}
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"suggest" : {
"my-suggest" : [
{
"text" : "jave",
"offset" : 0,
"length" : 4,
"options" : [
{
"text" : "java",
"score" : 0.75,
"freq" : 1
}
]
},
{
"text" : "开法",
"offset" : 4,
"length" : 2,
"options" : [ ]
},
{
"text" : "要",
"offset" : 6,
"length" : 1,
"options" : [ ]
},
{
"text" : "学",
"offset" : 7,
"length" : 1,
"options" : [ ]
},
{
"text" : "语音",
"offset" : 8,
"length" : 2,
"options" : [ ]
},
{
"text" : "吗",
"offset" : 10,
"length" : 1,
"options" : [ ]
}
]
}
}
2.5.10 搜索推荐
可以通过 match_phrase_prefix 匹配前缀 来达到搜索推荐的效果
GET goods/_search
{
"query": {
"match_phrase_prefix": {
"name": "华为"
}
}
}
2.5.11 智能纠错
官方给出了几种解决方案
1. 带高亮提示的
POST goods/_search
{
"suggest": {
"text": "jave",
"simple_phrase": {
"phrase": {
"field": "name",
"size": 1,
"gram_size": 3,
"direct_generator": [ {
"field": "name",
"suggest_mode": "always"
} ],
"highlight": {
"pre_tag": "<span color='red'>",
"post_tag": "</span>"
}
}
}
}
}
返回结果
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"suggest" : {
"simple_phrase" : [
{
"text" : "jave",
"offset" : 0,
"length" : 4,
"options" : [
{
"text" : "ja v e java",
"highlighted" : "ja v e <span color='red'>java</span>",
"score" : 3.2340043E-4
}
]
}
]
}
}
2. 普通的
POST goods/_search
{
"suggest": {
"text" : "jave",
"simple_phrase" : {
"phrase" : {
"field" : "name",
"size" : 1,
"smoothing" : {
"laplace" : {
"alpha" : 0.7
}
}
}
}
}
}
返回结果
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"suggest" : {
"simple_phrase" : [
{
"text" : "jave",
"offset" : 0,
"length" : 4,
"options" : [
{
"text" : "ja v e java",
"score" : 8.3273224E-4
}
]
}
]
}
}
复杂操作搜索 select ( 模糊查询,精准查询,排序,分页,高亮 等... !)
附、常用类型表
常用类型表
MySQL数据类型 | ES数据类型 | 说明 |
---|---|---|
int | Intrger | 如果源库中的类型为unsigned int,在Elasticsearch中使用long |
bigint | long | |
Bool Boolean | boolean | |
Decimal DEC | double | 如果decimal后面带小数点,为保证数据一致性,建议Elasticsearch中的数据类型使用text |
double | double | |
float | float | |
CHAR VARCHAR longtext | text | |
Date datetime | date | |
json | object | 如果bit只有一位,建议Elasticsearch中使用的数据类型为boolean |