文章目录

  • 1. Restful架构风格
  • 2. Es的倒排索引是什么?
  • 3. ES的重要概念
  • 4. 索引操作
  • 5. 文档操作
  • 6. 查询操作
  • 6.1 term & terms查询
  • 6.2 match_all & match & multi_match查询
  • 6.3 id & ids查询
  • 6.4 prefix & fuzzy查询
  • 6.5 wildcard & range & regexp查询
  • 6.6 scroll & delete-by-query
  • 6.7 bool & boosting查询
  • 6.8 filter & 高亮
  • 6.9 聚合查询


1. Restful架构风格

1、使用restful风格的url代替传统的url

传统的url:http://localhost:8989/xxx/find?id=1

RestUrl:http://localhost:8989/xxx/find/1

2、使用http的四种方法代替服务器的CRUD操作

es索引查看分片 es 查看索引_搜索

@GetMapping、@PostMaaping、@PutMapping、@GetMapping

@RequestMapping可以支持所有的请求方式,可以通过method属性指定请求方式

localhost://8080/rest/find?id=21
====>
localhost://8080/rest/find/21 

//需要通过@PathVariable从路径获取占位符id的值:@GetMapping、@GetMapping
@GetMapping("/rest/find/{id}")
public String test(@PathVariable String id){
	System.out.println(id);
    return "haha";
}
//前端通过post请求提交json格式的字符串:@PostMapping、@PutMapping

//使用@RequestBody接收json格式的字符串
@PostMapping("/update")
public String  test(@RequestBody User user){
	System.out.println(user);
    return "haha";
}

2. Es的倒排索引是什么?

Elasticsearch 是建立在全文搜索引擎库 Lucene 基础上的搜索引擎,它隐藏了 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API,不过掩盖不了它底层也是 Lucene 的事实。Elasticsearch 的倒排索引,其实就是 Lucene 的倒排索引。

传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引

倒排检索的好处:

  1. 比数据库模糊查询的效率高(数据库是正排索引,加入搜索一个单词,需要将全文扫描一遍,效率很低)
  2. 搜索结果存在相关度的排序
  3. 搜索时关键词不区分大小写

2、分词:

在创建索引之前会对文档的字符串进行分词,Elasticsearch中字符串类型包括keyword和text两种:

  • keyword:keyword类型的字符串不会被分词,搜索时全匹配查询
  • text:会被分词查询

不同的分词器对相同字符串分词的结果大有不同,选择不同的分词器对索引的创建有很大的影响

  • ik_max_word分词器: 最细粒度拆分
  • ik_smart分词器: 最粗粒度的拆分

3、单词文档矩阵:

从横向看,每行代表文档包含了哪些单词,比如文档1包含了单词1和单词3,而不包含其它单词。
从纵向看,每列代表了某个单词存在于哪些文档。比如单词1在文档1和文档4中出现过。

简单来说,索引就是实现“单词-文档矩阵”的具体数据结构,而倒排索引则是实现了这种数据结构的具体方式。

es索引查看分片 es 查看索引_es索引查看分片_02

4、倒排索引:

在倒排索引中,有三个名词:词条、词典、倒排表

词条:索引里面最小的存储和查询单元。一般来说,在英文语境中词条是一个单词,在中文语境中词条指的是分词后的一个词组。

词典:又称字典,是词条的集合。单词词典一般是由网页或文章集合中出现过的所有词构成的字符串集合。单词词典有两种数据结构实现:B+树Hash表。下面是Hash表的结构:

es索引查看分片 es 查看索引_es索引查看分片_03

倒排表:记录的是词出现在哪些文档里、出现的位置和频率等。在倒排表中,每条记录被称为一个倒排项。

es索引查看分片 es 查看索引_倒排索引_04

倒排索引为:

es索引查看分片 es 查看索引_搜索_05

比如单词“年度”,单词ID为2,在三个文档中出现过,所以逆向文档频率为3,同时倒排索引中的元素也有三个:(1;1;<2>),(2;1;<4>),(3;1;<3>)。拿第一个元素(1;1;<2>)进行说明,他表示“年度在文档ID为1的文档中出现过1次,出现的位置是第二个单词。

5、倒排索引的搜索过程:

es索引查看分片 es 查看索引_搜索_06

3. ES的重要概念

Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎。

es索引查看分片 es 查看索引_es索引查看分片_07

各版本的Es的内部结构:

es索引查看分片 es 查看索引_es索引查看分片_08

4. 索引操作

  1. 创建索引:
# 创建索引shop,并指明分片数和副本数
PUT /shop
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  }
}
  1. 删除索引:
DELETE /shop
  1. 查看索引:
GET /shop
  1. 创建type和mapping:
# 创建类型type
PUT /shop/_mapping/goods
{
  "properties": {
    "title": {
      "type": "text","analyzer":"ik_max_word"},
    "content":{
      "type":"text","analyzer":"ik_max_word"},
    "price": {"type": "float"},
    "stock": {"type": "integer"}
  }
}

5. 文档操作

  1. 单个文档操作:
# 添加文档
POST /book/novel/1{
  "name":"王五",
  "author":"赵六",
  "count":"20",
  "on-sale":"2020-12-2"
}

# 修改文档
POST /book/novel/1/_update{
  "doc":{
    "count":"123456"
  }
}

# 删除文档
DELETE /book/novel/1
  1. 批量处理文档:
# 批量修改语法
POST /test_index/test_type/_bulk
{"update":{"_id":12}}
{"doc":{"test_filed1":"test update bulk12"}}
{"update":{"_id":13}}
{"doc":{"test_filed1":"test update bulk13"}}

# 批量添加语法
POST /_bulk
{"create":{"_index":"test_index","_type":"test_type","_id":3}}
{"test_filed1":"test bulk create test3"}
{"create":{"_index":"test_index","_type":"test_type","_id":2}}
{"test_filed1":"test bulk create test2"}

# 批量删除语法
POST /_bulk
{"delete":{"_index":"test_index","_type":"test_type","_id":10}}
{"delete":{"_index":"test_index","_type":"test_type","_id":11}}
# 批量添加文档
POST /shop/goods/_bulk
{"index":{"_id":"1"}}
{"title":"小米手机很好用,但是不会的地方就是有时会发热,这一点让人很烦,但是作为一个大公司,相信会越来越好的","content":"小米手机","price":"2800","stock":"3800"}
{"index":{"_id":"2"}}
{"tilte":"OPPO手机感觉整体不错,但是我觉得他最大的缺点就是容易碎屏,把手机不小心摔下后,基本就不能使用了","content":"OPPO手机","price":"3000","stock":"3800"}
{"index":{"_id":"3"}}
{"title":"联想的电脑我真的不想吐槽,一个电脑用不了几天,就变的特别卡,搞不懂什么鬼","content":"联想电脑","price":"5000","stock":"6800"}
{"index":{"_id":"4"}}
{"title":"vivo,哇塞,是我最喜欢的手机品牌,性价比超高,不仅产量质量好,外观也非常漂亮,对于学生党,简直好的不要不要的","content":"vivo手机","price":"1000","stock":"3400"}
{"index":{"_id":"5"}}
{"tilte":"中兴,我不得不说,中兴的手机不行啊,之前买了一个中兴手机,用了一周,手机屏幕就碎了,然后换了一个,又用了一周,手机屏幕又碎了","content":"中兴手机和电脑","price":"7000","stock":"2900"}
{"index":{"_id":"6"}}
{"tilte":"三星的手机整体来将还是不错的,但是同样的东西和小米比,价格贵很多,这个对于穷女孩来说太不友好了","content":"三星手机和电脑","price":"3400","stock":"5000"}
{"index":{"_id":"7"}}
{"title":"苹果,苹果的价钱在那放着呢,要知道苹果手机使用的而并不是安卓系统,这个是塔比较特殊的地方","content":"苹果手机","price":"5000","stock":"2800"}
{"index":{"_id":"8"}}
{"tilte":"华为,瞅了瞅我的华为手机,屏幕已经不能看了,而且手机也很厚,外观也不漂亮,总之使用感觉很不好","content":"华为电脑","price":"6900","stock":"1000"}

# 批量查询
GET /shop/goods/_mget
{
  "ids":[1,2,3,4,5,6,7,8]
}

# 批量删除文档
POST /_bulk
{"delete":{"_index":"shop","_type":"goods","_id":"1"}}
{"delete":{"_index":"shop","_type":"goods","_id":"2"}}
{"delete":{"_index":"shop","_type":"goods","_id":"3"}}
{"delete":{"_index":"shop","_type":"goods","_id":"4"}}
{"delete":{"_index":"shop","_type":"goods","_id":"5"}}
{"delete":{"_index":"shop","_type":"goods","_id":"6"}}
{"delete":{"_index":"shop","_type":"goods","_id":"7"}}
{"delete":{"_index":"shop","_type":"goods","_id":"8"}}

6. 查询操作

6.1 term & terms查询

term 查询代表完全匹配的查询,搜索之前不会对你搜索的关键字进行分词。

将按照存储在倒排索引中的确切字词进行操作,这些查询通常用于数字,日期和枚举等结构化数据,而不是全文本字段。 或者,它们允许您制作低级查询,并在分析过程之前进行。

# term 查询
POST /shop/goods/_search
{
  "from": 0,
  "size": 2, 
  "query": {
    "term": {
      "stock": {
        "value": "1000"
      }
    }
  }
}

es索引查看分片 es 查看索引_es索引查看分片_09

注意:如果用于文档查询,查询结果不精确,比如:

# term 查询
POST /shop/goods/_search
{
  "from": 0,
  "size": 2, 
  "query": {
    "term": {
      "content": {
        "value": "小米手机"
      }
    }
  }
}

查询的结果显示为null:

es索引查看分片 es 查看索引_es索引查看分片_10

terms查询也不会将指定的查询关键字进行分词。可以指定字段的多个值

# terms查询:查询stock为3800、6800、1000的
POST /shop/goods/_search
{
  "query": {
    "terms": {
      "stock": [
        "3800","6800","1000"
      ]
    }
  }
}

查询结果:

es索引查看分片 es 查看索引_es索引查看分片_11

6.2 match_all & match & multi_match查询

match_all查询:代表查询所有

# match_all查询:代表查询所有
POST /shop/goods/_search
{
  "query": {
    "match_all": {}
  }
}

match查询,和term查询相反,会对关键字进行分词

# match查询:会对关键字进行分词
POST /shop/goods/_search
{
  "query": {
    "match": {
      "title": "华为手机"
    }
  }
}

结果:

es索引查看分片 es 查看索引_倒排索引_12

布尔match:and表示且,or表示又

es索引查看分片 es 查看索引_搜索_13

multi_match:多字段查询,只有有一个字段中含有关键字的分词就会匹配到

es索引查看分片 es 查看索引_搜索_14

6.3 id & ids查询

# id查询
GET /shop/goods/1

# ids查询
POST /shop/goods/_search
{
  "query": {
    "ids": {
      "values":["1","2"]
    }
  }
}

6.4 prefix & fuzzy查询

prefx查询:可以通过一个关键字指定一个field的前缀,从而查询到指定的文档

match查询:如果分词库中没有这个词是查不到的,而对于prefix即便分词库中没有这个次也可能查到

es索引查看分片 es 查看索引_es索引查看分片_15

fuzzy查询:模糊查询,fuzzy搜索以后,会自动尝试将你的搜索文本进行纠错,然后去跟文本进行匹配

但是如果错的比较严重,就不会匹配出结果(用于单词比较含演示,汉字不太好演示)

# fuzzy查询
POST /shop/goods/_search
{
  "query": {
    "fuzzy": {
      "content": {
        "value":"小米手即"
      }
    }
  }
}

6.5 wildcard & range & regexp查询

wildcard通配查询:类似于模糊查询,可以指定通配符* 和占位符?

# wildcard查询,不好用,很多时候查不到结果
POST /shop/goods/_search
{
  "query": {
    "wildcard": {
      "tilte": {
        "value": "*"
      }
    }
  }
}

range 范围查询:get:大于等于,gt:大于,lte:小于等于,lt:小于

es索引查看分片 es 查看索引_es索引查看分片_16

正则表达式查询:比如手机号,邮箱号等,因为没有设置这个字段,用价格来演示(注意本身不可以的)

# regexp查询
POST /shop/goods/_search
{
  "query": {
    "regexp": {
      "stock": "78[0-9]0"
    }
  }
}

6.6 scroll & delete-by-query

scroll查询用于分页查询

# scroll查询
POST /shop/goods/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

# 查询第二页的数据
POST /_search/scroll
{
  "scroll_id":"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAANXCFmpVd3R5VkpzVDNhOXdZOVVrUU9lYncAAAAAAADVxBZqVXd0eVZKc1QzYTl3WTlVa1FPZWJ3AAAAAAAA1cMWalV3dHlWSnNUM2E5d1k5VWtRT2Vidw==",
  "scroll": "1m"
  
}

# 删除scroll在上下文中的数据
DELETE /_search/scroll/"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAANXCFmpVd3R5VkpzVDNhOXdZOVVrUU9lYncAAAAAAADVxBZqVXd0eVZKc1QzYTl3WTlVa1FPZWJ3AAAAAAAA1cMWalV3dHlWSnNUM2E5d1k5VWtRT2Vidw=="

delete-by-query:删除查询到的数据

# delete-by-query
POST /shop/goods/_delete_by_query
{
 "query": {
    "range": {
      "price": {
        "gte": 0,
        "lte": 2000
      }
    }
  }
}

6.7 bool & boosting查询

bool查询:

must:amd

must_not :将must_not 中的数据全部都不匹配

should:or

# title中包含小米和手机
# 价格为5000 或 7000
# 库存不是 2900
# bool查询
POST /shop/goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "price": {
              "value": "5000"
            }
          }
        },
        {
          "term": {
            "price": {
              "value": "7000"
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "stock": {
              "value": "2900"
            }
          }
        }
      ],
      "must": [
        {
          "match": {
            "title": "小米"
          }
        },
        {
          "match": {
            "title": "手机"
          }
        }
      ]
    }
  }
}

boosting查询:

positive:只有匹配到了positive的内容,才会被放到结果集中

nagtive:既匹配了positive也匹配了nagtive,就可以降低这个文档的score

# boosting查询
# 既匹配了“华为”,又匹配了“手机”的选项score需要乘以0.2
POST /shop/goods/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "tilte": "华为"
        }
      },
      "negative": {
        "match": {
          "tilte": "手机"
        }
      },
      "negative_boost": 0.2
    }
  }
}

6.8 filter & 高亮

filter :查询文档,不计算分数也就不会排序,经常会对过滤的数据进行缓存

POST /shop/goods/_search
{
  "query": {
    "bool": {
      "filter": [{
        "term":{
          "title":"手机"
          }
        },
        {
          "range":{
            "price":{
              "lte":3000
            }
          }
        }
      ]
    }
  }
}

highlight:高亮显示

POST /shop/goods/_search
{
  "query": {
    "match": {
      "title": "手机"
    }
  },
  "highlight": {
    "fields": {
      "title": {}
    },
    "pre_tags": "<font color='red'>",
    "post_tags": "</font>", 
    "fragment_size": 5
  }
}

6.9 聚合查询

# 去重计数
POST /shop/goods/_search
{
  "aggs": {
    "agg": {
      "cardinality": {
        "field": "price"
      }
    }
  }
}

# 统计一定范围内的文档的个数
POST /shop/goods/_search
{
  "aggs": {
    "agg": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "to": 50
          },
          {
            "from": 50,
            "to": 5000
          },
          {
            "from": 5000
          }
        ]
      }
    }
  }
}

# 查询指定的filed的最大值,最小值,平均值等
POST /shop/goods/_search
{
  "aggs": {
    "agg": {
      "extended_stats": {
        "field": "price"
      }
    }
  }
}