ES的倒排索引和ES与Mysql的使用对比

什么是ES:

  • ES全称是ElasticSearch,是一个开源的搜索引擎,可以帮助我们快速从海量数据里搜索到需要的数据;

为什么要有ES:MySql或其它传统的RDBMS有一些问题

  • 模糊查询时,如果查询条件是以%开头,那么查询的性能会急剧下降
  • 文本检索结果不精确。比如要搜索%华为手机%,搜索不到华为Mate50HUAWEI Mate50华为 手机

正向索引:如果要检索一条数据,需要全表扫描。数据量越大,性能下降就越严重

  • 先获取第一条,判断是否匹配搜索条件;如果不匹配,就抛弃;如果匹配,就留下
  • 再获取第二条,判断是否匹配搜索条件;如果不匹配,就抛弃;如果匹配,就留下
  • ……
  • 获取最后一条,判断是否匹配搜索条件;如果不匹配,就抛弃;如果匹配,就留下

倒排索引:

  • 给某个字段值构建倒排索引:

    对这个字段的所有值,都进行分词。构建一下 拆分的词条与文档id的对应关系,这个对应关系是倒排索引

  • 要检索一个数据:

    要对检索的关键词进行分词

    拿拆分的词条,去倒排索引里直接找到关联的文档有哪些

    不需要全表扫描了

ES和MySQL的对比:

  • 相同点:它们都能够存储数据,都能够进行增删改查操作
  • 不同点:
    • MySQL擅长事务型 的操作(增删改),可以保证数据的安全性和一致性
    • ES擅长是数据查询搜索统计分析操作(查),查询的性能极强
  • 实际使用模式:
    • 要增删改数据,操作MySQL
    • 要查询数据,从es里查询
    • 后台从MySQL里,把数据同步到es里

操作ES索引库的命令

#1. 创建索引库(相当于MySql的建表)
#字段名:我们自定义
#每个字段要设置:
#type:字段的类型。int,short,long,double, text, keyword,…
#字段串1:text,要使用分词器进行分词的。 必须要设置用哪种分词器
#字符串2:keyword,不分词的字符串,比如:行政区域划分 省、市、县,url地址
#index:boolean类型,这个字段是否参与构建索引(是否能根据这个字段搜索数据)
PUT /product
{
“mappings”: {
“properties”: {
“id”:{
“type”: “long”,
“index”: true
},
“name”:{
“type”: “text”,
“analyzer”: “ik_max_word”
},
“image”:{
“type”: “keyword”,
“index”: false
},
“price”:{
“type”: “double”
}
}
}
}
#2. 查看所有索引库
GET /_cat/indices
GET /_cat/indices?v
#3. 查看某一个索引库
GET /product
#4. 修改某一个索引库
#注意:不能修改已有字段,只允许增加新字段
PUT /product/_mapping
{
“properties”:{
“brand”:{
“type”: “keyword”
}
}
}
#5. 删除某一个索引库
DELETE /product

操作ES文档的命令

#---------操作文档(操作数据)------------
#1. 查询索引库里的所有文档数据:搜索全部
GET /product/_search
{
“query”: {
“match_all”: {}
}
}
#2. 新增一条文档数据,修改一条文档数据(这个命令是保存操作,有就覆盖,没有就新增)
PUT /product/_doc/1
{
“id”: 1,
“name”: “HUAWEI Mate50 Pro 黑色”,
“brand”: “华为”,
“price”: 3999,
“image”: “http://www.huawei.com/mall/mate50.jpb”
}
#3. 查看一条文档数据
GET /product/_doc/1
#4. 修改一条文档数据
#全量修改:直接把原数据覆盖掉
PUT /product/_doc/1
{
“brand”: “HUAWEI”
}
#增量修改:在原本数据基础上做修改变化
POST /product/_update/1
{
“doc”: {
“id”:1,
“name”: “华为Mate50 pro 磨砂黑”,
“price”: 3999,
“image”: “http://www.huawei.com/mall/mate50.jpg”,
“brand”: “华为”
}
}
#5. 删除一条文档数据
DELETE /product/_doc/1

Java代码操作ES的步骤

  1. 使用JavaAPI操作es的统一步骤
//1. 创建客户端对象,连接es服务
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
	new HttpHost("localhost", 9200)
));

//2. 使用client对象操作es

//3. 关闭client对象
client.close();
  1. 使用JavaAPI操作索引库
//1. 创建索引库:注意不要导错CreateIndexRequest类了,有两个同名类,导那个短的
CreateIndexRequest request = new CreateIndexRequest("索引库名称")
    .source("索引库的结构json语句", XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);

//2. 判断索引库是否存在
GetIndexRequest request = new GetIndexRequest("索引库名");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);

//3. 删除索引库
DeleteIndexRequest request = new DeleteIndexRequest("索引库名");
client.indices().delete(request, RequestOptions.DEFAULT);
  1. 使用JavaAPI操作文档
//1. 保存文档(如果文档不存在是新增,如果已存在是修改)
IndexRequest request = new IndexRequest("索引库名")
    .id("文档的唯一标识字符串")
    .source("文档内容json字符串", XContentType.JSON)
client.index(request, RequestOptions.DEFAULT);

//2. 根据id获取文档
GetRequest request = new GetRequest("索引库名").id("文档的唯一标识字符串");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String docJson = response.getSourceAsString();

//3. 根据id删除文档
DeleteRequest request = new DeteteRequest("索引库名").id("文档的唯一标识字符串");
client.delete(request, RequestOptions.DEFAULT);
  1. 批量操作文档
BulkRequest request = new BulkRequest();
循环某一个列表:
    IndexRequest indexRequest = .....;
    request.add(indexRequest);

client.bulk(request, RequestOptions.DEFAULT);
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。