Elasticsearch笔记

第1章 Elasticsearch 概述

1.1 Elasticsearch 是什么

在这里插入图片描述
The Elastic Stack, 包括 Elasticsearch、Kibana、Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。Elaticsearch,简称为 ES,ES 是一个开源的高扩展的分布式全文搜索引擎,是整个 ElasticStack 技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。

1.2 全文搜索引擎

Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差
的:

  • 搜索的数据对象是大量的非结构化的文本数据。
  • 文件记录量达到数十万或数百万个甚至更多。
  • 支持大量基于交互式文本的查询。
  • 需求非常灵活的全文搜索查询。
  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。

为了解决结构化数据搜索和非结构化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

第2章 Elasticsearch 入门

2.1 Elasticsearch 安装

2.2 Elasticsearch 基本操作

2.2.1 RESTful

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。
在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI(Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和DELETE。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、PUT、DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以及对资源进行的操作(增删改查)。

2.2.2 客户端安装

如果直接通过浏览器向 Elasticsearch 服务器发请求,那么需要在发送的请求中包含HTTP 标准的方法,而 HTTP 的大部分特性且仅支持 GET 和 POST 方法。所以为了能方便地进行客户端的访问,可以使用 Postman 软件

2.2.3 数据格式

Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解,我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比
在这里插入图片描述
ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个type,Elasticsearch 7.X 中, Type 的概念已经被删除了。

2.2.4 HTTP 操作

2.2.4.1 索引操作
1) 创建索引

对比关系型数据库,创建索引就等同于创建数据库
在 Postman 中,向 ES 服务器发 PUT 请求 :http://192.168.80.130/shopping
在这里插入图片描述

{
"acknowledged"【响应结果】: true, # true 操作成功
"shards_acknowledged"【分片结果】: true, # 分片操作成功
"index"【索引名称】: "shopping"
}

如果重复添加索引,会返回错误信息

2) 查看所有索引
192.168.80.130:9200/_cat/indices?v

这里请求路径中的_cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉,服务器响应结果如下
在这里插入图片描述

在这里插入图片描述

3) 查看单个索引

在 Postman 中,向 ES 服务器发 GET 请求 :192.168.80.130:9200/shopping
在这里插入图片描述
在这里插入图片描述

4) 删除索引

在 Postman 中,向 ES 服务器发 DELETE 请求 :192.168.80.130:9200/shopping
在这里插入图片描述

重新访问索引时,服务器返回响应:索引不存在
在这里插入图片描述

2.2.4.2 文档操作
1) 创建文档

索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式在 Postman 中,向 ES 服务器发 POST 请求 :192.168.80.131:9200/shopping/phone/1
请求体内容为:

{
 "title":"小米手机",
 "category":"小米",
 "images":"http://www.gulixueyuan.com/xm.jpg",
 "price":3999.00
}

在这里插入图片描述192.168.80.131:9200/shopping/phone/1可以用post请求也可以用put请求,这里id已近确定为1.
192.168.80.131:9200/shopping/phone 只能用post请求,每次请求的id不一样,id随机生成,post不具有幂等性,而put有幂等性。

2) 查看文档
1 查看单个文档

查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询
在 Postman 中,向 ES 服务器发 GET 请求:192.168.80.131:9200/shopping/phone/1
在这里插入图片描述

2查看所有文档

192.168.80.131:9200/shopping/_search
在这里插入图片描述

3) 修改文档

和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖在 Postman 中,向 ES 服务器发 POST 请求 :192.168.80.131:9200/shopping/phone/1
请求体内容为

{
 "title":"华为手机",
 "category":"华为",
 "images":"http://www.gulixueyuan.com/hw.jpg",
 "price":4999.00
}

在这里插入图片描述

4) 修改字段

在这里插入图片描述

5) 删除文档

删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
在这里插入图片描述

6) 条件查询
1 url形式

192.168.80.131:9200/shopping/_search?q=title:小米手机

2 body携带json

在这里插入图片描述

7)分页查询

在这里插入图片描述

8)查询指定字段

在这里插入图片描述

9)排序

在这里插入图片描述

10) 多条件查询
1 and

在这里插入图片描述

2 or

在这里插入图片描述

11) 全文匹配

在这里插入图片描述

12)查询内容高亮显示

在这里插入图片描述

13)分组

在这里插入图片描述

14)求平均值、最大值、最小值、sum等

在这里插入图片描述最大值“avg”换为“max”,最大值“avg”换为“min”

15)State 聚合

stats 聚合,对某个字段一次性返回 count,max,min,avg 和 sum 五个指标
在这里插入图片描述

xx) 条件删除文档

在这里插入图片描述

2.2.4.3 映射操作

有了索引库,等于有了数据库中的 database。
接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。

1) 创建映射

先创建索引才能创建映射
在这里插入图片描述

2.2.5 Java API 操作

Elasticsearch 软件是由 Java 语言开发的,所以也可以通过 Java API 的方式对 Elasticsearch服务进行访问

2.2.5.1 创建 Maven 项目

修改 pom 文件,增加 Maven 依赖关系

<dependencies>
	<dependency>
		<groupId>org.elasticsearch</groupId>
		<artifactId>elasticsearch</artifactId>
		<version>7.8.0</version>
	</dependency>
	<!-- elasticsearch 的客户端 -->
	<dependency>
		<groupId>org.elasticsearch.client</groupId>
		<artifactId>elasticsearch-rest-high-level-client</artifactId>
		<version>7.8.0</version>
	</dependency>
	<!-- elasticsearch 依赖 2.x 的 log4j -->
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-api</artifactId>
		<version>2.8.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.logging.log4j</groupId>
		<artifactId>log4j-core</artifactId>
		<version>2.8.2</version>
	</dependency>
	<dependency>
		<groupId>com.fasterxml.jackson.core</groupId>
		<artifactId>jackson-databind</artifactId>
		<version>2.9.9</version>
	</dependency>
	<!-- junit 单元测试 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
	</dependency>
</dependencies>
2.2.5.2 客户端对象

代码中创建 Elasticsearch 客户端对象因为早期版本的客户端对象已经不再推荐使用,且在未来版本中会被删除,所以这里我们采用高级 REST 客户端对象

 esClient =new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.80.131", 9200, "http")));
2.2.5.3 索引操作
1) 创建索引
public static void createIndex(String indexName) throws IOException {
        CreateIndexRequest user = new CreateIndexRequest(indexName);
        CreateIndexResponse indexResponse = esClient.indices().create(user, RequestOptions.DEFAULT);
        //相应状态
        boolean acknowledged = indexResponse.isAcknowledged();
        System.out.println("索引操作"+acknowledged);
    }
2) 查看索引
 public static void queryIndex(String indexName) throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
        GetIndexResponse response = esClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(response.getAliases());
        System.out.println(response.getMappings());
        System.out.println(response.getSettings());
    }
3) 删除索引
 public static void deleteIndex(String indexName) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
    }
2.2.5.4 文档操作
1) 新增文档

创建数据模型

public class User {
    private String name;
    private String sex;
    private Integer age;

    public User(String name, String sex, Integer age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}

创建数据,添加到文档中

 public static void insert(String indexName,String id, User user) throws IOException {
        IndexRequest request =new IndexRequest();
        request.index(indexName).id(id).source(mapper.writeValueAsString(user), XContentType.JSON);
        IndexResponse response =
                esClient.index(request, RequestOptions.DEFAULT);
        System.out.println(response.getResult());

    }
2) 修改文档
 public static void update(String indexName, String id, String... args) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(indexName,id);
        updateRequest.doc(XContentType.JSON,args[0],args[1]);
        UpdateResponse response = esClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println("修改数据成功");
    }
3) 查询文档
public static void query(String indexName, String id, String... args) throws IOException {
        GetRequest request = new GetRequest(indexName,id);
        GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsString());
        System.out.println("查询数据成功");
    }
4) 删除文档
 public static void delete(String indexName, String id) throws IOException {
        DeleteRequest request = new DeleteRequest(indexName,id);
        DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
        System.out.println(response.toString());
    }
5) 批量操作
1 批量新增
  public static void batchInsert(String indexName) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.add(new IndexRequest().index(indexName).id("1001").source(XContentType.JSON,"name","张三","age",21,"sex","男"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1002").source(XContentType.JSON,"name","李四","age",22,"sex","女"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1003").source(XContentType.JSON,"name","王五","age",23,"sex","男"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1004").source(XContentType.JSON,"name","赵六","age",23,"sex","男"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1005").source(XContentType.JSON,"name","王五1","age",22,"sex","女"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1006").source(XContentType.JSON,"name","王五2","age",21,"sex","男"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1007").source(XContentType.JSON,"name","张三1","age",19,"sex","男"));
        bulkRequest.add(new IndexRequest().index(indexName).id("1008").source(XContentType.JSON,"name","zhangsan","age",19,"sex","男"));
        BulkResponse bulk = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulk.getTook());
        System.out.println(bulk.getItems());
    }
2 批量删除
//创建批量删除请求对象
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest().index("user").id("1001"));
request.add(new DeleteRequest().index("user").id("1002"));
request.add(new DeleteRequest().index("user").id("1003"));
//客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
//打印结果信息
System.out.println("took:" + responses.getTook());
System.out.println("items:" + responses.getItems());
2.2.5.5 高级查询
1 查询所有数据
public static void queryAll(String indexName) throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices(indexName).source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        TotalHits totalHits = hits.getTotalHits();
        for (SearchHit hit: hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
2 term 查询,查询条件为关键字
public static void queryCondition(String indexName) throws IOException {
        SearchRequest request = new SearchRequest();
        request.indices(indexName).source(new SearchSourceBuilder().query(QueryBuilders.termQuery("age",23)));
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        TotalHits totalHits = hits.getTotalHits();
        for (SearchHit hit: hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
3 分页查询
 public static void queryBool(String indexName) throws IOException {
        SearchRequest request = new SearchRequest();                //(当前页码-1)*每页条数
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            builder.must(QueryBuilders.matchQuery("age",23));
            builder.must(QueryBuilders.matchQuery("sex", "男"));
        searchSourceBuilder.query(builder);
        request.source(searchSourceBuilder);
        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();
        TotalHits totalHits = hits.getTotalHits();
        for (SearchHit hit: hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
4 数据排序、过滤
 public static void queryPageAOrderAFilter(String indexName) throws IOException {
            SearchRequest request = new SearchRequest();                //(当前页码-1)*每页条数
            SearchSourceBuilder builder = new SearchSourceBuilder();
            String[] excludes = {};
            String[] includes = {"name"};
            builder.sort("age",SortOrder.DESC)
                    .from(0).size(5).
                    fetchSource(includes,excludes).
                    query(QueryBuilders.matchAllQuery());
            request.source(builder);
            SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
            SearchHits hits = response.getHits();
            TotalHits totalHits = hits.getTotalHits();
            for (SearchHit hit: hits) {
                System.out.println(hit.getSourceAsString());
            }
    }
5 Bool 查询
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("student");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 必须包含
boolQueryBuilder.must(QueryBuilders.matchQuery("age", "30"));
// 一定不含
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name", "zhangsan"));
// 可能包含
boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "男"));
sourceBuilder.query(boolQueryBuilder);
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 查询匹配
SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
6 范围查询
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("student");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
// 大于等于
rangeQuery.gte("30");
// 小于等于
rangeQuery.lte("40");
sourceBuilder.query(rangeQuery);
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 查询匹配
SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
7 模糊查询
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("student");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.fuzzyQuery("name","zhangsan").fuzziness(Fu
zziness.ONE));
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 查询匹配
SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
8 高亮查询
// 高亮查询
SearchRequest request = new SearchRequest().indices("student");
//2.创建查询请求体构建器
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构建查询方式:高亮查询
TermsQueryBuilder termsQueryBuilder =
QueryBuilders.termsQuery("name","zhangsan");
//设置查询方式
sourceBuilder.query(termsQueryBuilder);
//构建高亮字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>");//设置标签前缀
highlightBuilder.postTags("</font>");//设置标签后缀
highlightBuilder.field("name");//设置高亮字段
//设置高亮构建对象
sourceBuilder.highlighter(highlightBuilder);
//设置请求体
request.source(sourceBuilder);
//3.客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.打印响应结果
SearchHits hits = response.getHits();
System.out.println("took::"+response.getTook());
System.out.println("time_out::"+response.isTimedOut());
System.out.println("total::"+hits.getTotalHits());
System.out.println("max_score::"+hits.getMaxScore());
System.out.println("hits::::>>");
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
//打印高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
System.out.println(highlightFields);
}
System.out.println("<<::::");
9 聚合查询
最大年龄
// 高亮查询
SearchRequest request = new SearchRequest().indices("student");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.max("maxAge").field("age"));
//设置请求体
request.source(sourceBuilder);
//3.客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.打印响应结果
SearchHits hits = response.getHits();
System.out.println(response);
分组统计
// 高亮查询
SearchRequest request = new SearchRequest().indices("student");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.terms("age_groupby").field("ag
e"));
//设置请求体
request.source(sourceBuilder);
//3.客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//4.打印响应结果
SearchHits hits = response.getHits();
System.out.println(response);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值