docker搭建elasticsearch、kibana,并集成至spring boot
步骤如下:
一、基于docker搭建elasticsearch环境
1、拉取镜像
docker pull elasticsearch5.6.8
2、制作elasticsearch的配置文件
master配置
http.host: 0.0.0.0
#集群名称 所有节点要相同
cluster.name: "estest"
#本节点名称
node.name: master
#作为master节点
node.master: true
#是否存储数据
node.data: true
bootstrap.system_call_filter: false
transport.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1
slave配置
http.host: 0.0.0.0
#集群名称 所有节点要相同
cluster.name: "estest"
#子节点名称
node.name: slave1
#不作为master节点
node.master: false
node.data: true
bootstrap.system_call_filter: false
transport.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1
discovery.zen.ping.unicast.hosts: ["esmaster:9300"]
注意salve节点的discovery.zen.ping.unicast.hosts设置为esmaster:9300,这里的esmaster是master节点的docker容器名字
3、启动容器
master容器
docker run -d --name esmaster --ulimit nofile=65536:131072 -p 9200:9200 -p 9300:9300 -v /home/es/config/master.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /home/es/master:/usr/share/elasticsearch/data -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" elasticsearch:5.6.8
参数说明:
--name esmaster
指定容器名称为esmater,salve节点配置文件中的discovery.zen.ping.unicast.hosts要和这里对应,因为salve容器和master容器之间的是通过 --linkM指令来通信的。
--ulimit nofile=65536:131072
避免容器启动时会报bootstrap checks failed异常
-- -p 9200:9200 -p 9300:9300
暴露出容器的9200,9300端口到宿主机的9200,9300端口
-- -v C:/work/docker_volume/elasticsearch/elasticsearchmaster.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v C:/work/docker_volume/elasticsearch/data/master:/usr/share/elasticsearch/data
挂载卷到容器中,其实就是设置容器配置文件关联上面写好的配置文件,容器存储数据关联到宿主机的外部文件中
-- -e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
设置容器内Java虚拟机的内存大小
salve容器
docker run -d --name esslave1 --ulimit nofile=65536:131072 --link esmaster:esmaster -v /home/es/config/slave1.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /home/es/slave1:/usr/share/elasticsearch/data -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" elasticsearch:5.6.8
主要是使用--link esmaster:esmaster指令,来连接master容器,别的和master容器启动参数基本一样。
浏览器输入curl localhost:9200验证一下
{
"name" : "master",
"cluster_name" : "estest",
"cluster_uuid" : "x1-qThTBRA6GQr_sdjYMGw",
"version" : {
"number" : "5.6.8",
"build_hash" : "688ecce",
"build_date" : "2018-02-16T16:46:30.010Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
说明elasticsearch已经启动成功
二、kibana
1、拉取镜像
docker pull kibana:5.6.14
2、启动镜像
docker run -it -d -e ELASTICSEARCH_URL=http://172.17.0.2:9200 -p 5601:5601 --name kibana kibana:5.6.14
注意ELASTICSEARCH_URL中配的是es容器的docker内部ip,可以通过如下方式查看
docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>
3、http://localhost:5601访问即可
三、es与springboot集成
1、pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</dependency>
2、工具类
@Slf4j
@Component
@ConditionalOnProperty(name = "elasticsearch.enabled")
public class ElasticUtil { private static JestClient jestClient; /**
* 向elasticsearch中插入一条记录
*
* @param t 数据
* @param index 索引名
* @param type 类型名
* @param <T>
* @return 插入结果
*/
public static <T> Result save(T t, String index, String type) {
if (t == null || StringUtils.isBlank(index) || StringUtils.isBlank(type)) {
return Result.getResult(Constant.FAIL, "缺少参数");
}
Index indexBuilder = new Index.Builder(t).index(index).type(type).build();
try {
DocumentResult execute = jestClient.execute(indexBuilder);
return Result.getResult(Constant.SUCCESS, "插入elasticsearch成功", execute);
} catch (IOException e) {
log.error("插入elasticsearch异常", e);
return Result.getResult(Constant.ERROR, "插入elasticsearch异常");
}
} /**
* 向elasticsearch中批量插入多条记录
*
* @param list 数据
* @param index 索引名
* @param type 类型名
* @param <T>
* @return 插入结果
*/
public static <T> Result saveAll(List<T> list, String index, String type) {
if (list == null || list.size() == 0 || StringUtils.isBlank(index) || StringUtils.isBlank(type)) {
return Result.getResult(Constant.FAIL, "缺少参数");
}
Bulk.Builder bulkBuilder = new Bulk.Builder();
/*list.stream().forEach(data -> {
Index indexBuilder = new Index.Builder(data).index(index).type(type).build();
bulkBuilder.addAction(indexBuilder);
});*/
List<Index> indexList = list.stream().map(data -> new Index.Builder(data).index(index).type(type).build()).collect(toList());
bulkBuilder.addAction(indexList);
try {
jestClient.execute(bulkBuilder.build());
return Result.getResult(Constant.SUCCESS, "批量插入elasticsearch成功");
} catch (IOException e) {
log.error("批量插入elasticsearch异常", e);
return Result.getResult(Constant.ERROR, "批量插入elasticsearch异常");
}
} /**
* 根据id修改文档
*
* @param t 修改数据
* @param index 索引
* @param type 类型
* @param id 主键
* @param <T>
* @return 修改结果
*/
public static <T> Result updateById(T t, String index, String type, String id) {
if (t == null || StringUtils.isBlank(index) || StringUtils.isBlank(type) || StringUtils.isBlank(id)) {
return Result.getResult(Constant.FAIL, "缺少参数");
}
try {
String doc = XContentFactory.jsonBuilder().startObject().field("doc", JSONObject.toJSON(t)).endObject().string();
Update updateBuilder = new Update.Builder(doc).index(index).type(type).id(id).build();
DocumentResult execute = jestClient.execute(updateBuilder);
return Result.getResult(Constant.SUCCESS, "修改elasticsearch文档成功", execute);
} catch (IOException e) {
log.error("XContentFactory构造JSON异常", e);
return Result.getResult(Constant.ERROR, "XContentFactory构造JSON异常");
} catch (Exception e) {
log.error("修改elasticsearch文档异常", e);
return Result.getResult(Constant.ERROR, "修改elasticsearch文档异常");
}
} /**
* 根据主键删除文档
*
* @param index 索引
* @param type 类型
* @param id 主键
* @return
*/
public static Result deleteById(String index, String type, String id) {
if (StringUtils.isBlank(index) || StringUtils.isBlank(type) || StringUtils.isBlank(id)) {
return Result.getResult(Constant.FAIL, "缺少参数");
}
try {
Delete deleteBuilder = new Delete.Builder(id).index(index).type(type).build();
DocumentResult execute = jestClient.execute(deleteBuilder);
return Result.getResult(Constant.SUCCESS, "删除elasticsearch文档成功", execute);
} catch (Exception e) {
log.error("删除elasticsearch文档异常", e);
return Result.getResult(Constant.ERROR, "删除elasticsearch文档异常");
}
} /**
* 分页查询
*
* @param clazz 数据类型
* @param elasticSearchBean 查询对象
* @param <T>
* @return 查询结果
*/
public static <T> Result get(Class<T> clazz, ElasticSearchBean elasticSearchBean) {
try {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
AbstractQueryBuilder queryStringQueryBuilder = null;
if(elasticSearchBean.isFullTextMatching()){
queryStringQueryBuilder = QueryBuilders.queryStringQuery(elasticSearchBean.getKeyword());
}else {
queryStringQueryBuilder = QueryBuilders.multiMatchQuery(elasticSearchBean.getKeyword(), (String[]) elasticSearchBean.getMatchingFields().toArray());
}
searchSourceBuilder.query(queryStringQueryBuilder);
if(null != elasticSearchBean.getHighLightsFields()){
HighlightBuilder highlightBuilder = new HighlightBuilder();
elasticSearchBean.getHighLightsFields().stream().forEach(field -> highlightBuilder.field(field));
// HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);
highlightBuilder.requireFieldMatch(false);
//高亮标签
highlightBuilder.preTags("<em>").postTags("</em>");
//高亮内容长度
highlightBuilder.fragmentSize(200);
searchSourceBuilder.highlighter(highlightBuilder);
}
Search.Builder searchBuilder = new Search.Builder(
searchSourceBuilder.toString())
.addIndex(elasticSearchBean.getIndex())
.addType(elasticSearchBean.getType());
if(null != elasticSearchBean.getFrom()){
searchBuilder.setParameter("from", elasticSearchBean.getFrom());
}
if(null != elasticSearchBean.getSize()){
searchBuilder.setParameter("size", elasticSearchBean.getSize());
} if(null != elasticSearchBean.getSortFields() && elasticSearchBean.getSortFields().size() > 0){
searchBuilder.addSort(elasticSearchBean.getSortFields());
}
// .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) //设置查询类型:1.SearchType.DFS_QUERY_THEN_FETCH 精确查询; 2.SearchType.SCAN 扫描查询,无序
Search search = searchBuilder.build();
SearchResult searchResult = jestClient.execute(search);
if(!searchResult.isSucceeded()){
return Result.getResult(Constant.FAIL,searchResult.getErrorMessage());
}
List<JSONObject> data = searchResult.getHits(clazz).stream().map(hit -> {
JSONObject json = (JSONObject) JSONObject.toJSON(hit.source);
json.put("esId", hit.id);
Map<String, List<String>> highlight = hit.highlight;
for (String key : highlight.keySet()) {
json.put(key, highlight.get(key).get(0));
}
return json;
}).collect(toList()); return Result.getResult(Constant.SUCCESS, "elasticsearch查询成功", data, searchResult.getTotal().intValue());
} catch (IOException e) {
log.error("elasticsearch查询异常", e);
return Result.getResult(Constant.ERROR, "elasticsearch查询异常");
}
} @Resource
public void setJestClient(JestClient jestClient) {
ElasticUtil.jestClient = jestClient;
}
}
3、抽象出一个类,封装查询时要传递的各种参数
@Data
public class ElasticSearchBean implements Serializable {
private static final long serialVersionUID = -5188975204258390540L;
/**
* 索引
*/
private String index;
/**
* 类型
*/
private String type;
/**
* 要查询关键字
*/
private String keyword;
/**
* 从第几行开始
*/
private Integer from;
/**
* 查询几条数据
*/
private Integer size;
/**
* 高亮字段
*/
private List<String> highLightsFields;
/**
* 排序字段
*/
private List<Sort> sortFields;
/**
* 是否是全文匹配,true:是;false;不是
*/
private boolean isFullTextMatching;
/**
* 要匹配的字段
*/
private List<String> MatchingFields; }
4、测试
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = SswApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class ElasticSearchTest {
@Test
public void saveTest() {
User user = new User();
user.setRealName("王五");
user.setLoginName("wangwu");
user.setAge(19);
user.setGender(true);
user.setStatus(0);
Result result = ElasticUtil.save(user, "user", "user");
System.out.println(result.getFlag());
System.out.println(result.getMsg());
}
@Test
public void updateTest() {
User user = new User();
user.setRealName("王五2号");
user.setLoginName("wangwu");
user.setAge(19);
user.setGender(true);
user.setStatus(0);
Result result = ElasticUtil.updateById(user, "user", "user","AWLxcPgxbdesqcfPx6TL");
System.out.println(result.getFlag());
System.out.println(result.getMsg());
}
@Test
public void deleteTest() {
Result result = ElasticUtil.deleteById("user", "user","AWLxcPgxbdesqcfPx6TL");
System.out.println(result.getFlag());
System.out.println(result.getMsg());
}
@Test
public void searchTest() {
Class clazz = User.class;
String index = "user";
String type = "user";
String keyword = "王";
int from = 0;
int size = 10;
List<String> highLightsFields = Arrays.asList(new String[]{"realName","loginName"});
List<Sort> sortFields = Arrays.asList(new Sort[]{new Sort("realName",Sort.Sorting.DESC),new Sort("loginName",Sort.Sorting.ASC)});
List<String> matchingFields = Arrays.asList(new String[]{"password","email"});
ElasticSearchBean elasticSearchBean = new ElasticSearchBean();
elasticSearchBean.setIndex(index);
elasticSearchBean.setType(type);
elasticSearchBean.setKeyword(keyword);
elasticSearchBean.setFrom(from);
elasticSearchBean.setSize(size);
elasticSearchBean.setHighLightsFields(highLightsFields);
elasticSearchBean.setFullTextMatching(true);
elasticSearchBean.setSortFields(sortFields);
elasticSearchBean.setMatchingFields(matchingFields); Result result = ElasticUtil.get(clazz, elasticSearchBean);
System.out.println(result.getFlag());
System.out.println(result.getMsg());
System.out.println(result.getTotal());
System.out.println(result.getData());
}
}
注意,在排序的时候,有时候会报异常
Fielddata is disabled on text fields by default. Set fielddata=true on [realName] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory.
这是因为elasticsearch对于text类型的字段,默认是不支持排序的,需要设置,方法如下:
发一个put请求:
http://localhost:9200/index/_mapping/type
请求体为
{
"properties": {
"realName": {
"type": "text",
"fielddata": true
}
}
}
如果返回
{"acknowledged":true}
说明设置成功,再排序就没有问题了
docker搭建elasticsearch、kibana,并集成至spring boot的更多相关文章
- 【ELK】【docker】【elasticsearch】1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安装ik分词器
系列文章:[建议从第二章开始] [ELK][docker][elasticsearch]1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安 ...
- Elasticsearch使用系列-Docker搭建Elasticsearch集群
Elasticsearch使用系列-ES简介和环境搭建 Elasticsearch使用系列-ES增删查改基本操作+ik分词 Elasticsearch使用系列-基本查询和聚合查询+sql插件 Elas ...
- 【最新】docker 安装elasticsearch + kibana步骤【第一篇_elasticsearch】
最近在用docker 安装elasticsearch + kibana 遇到了很多坑,最后成功安装elasticsearch + kibana (6.8.1)版本 安装了一下午,现总结过程中遇到 ...
- 实战:docker搭建FastDFS文件系统并集成SpringBoot
实战:docker搭建FastDFS文件系统并集成SpringBoot 前言 15年的时候,那时候云存储还远远没有现在使用的这么广泛,归根结底就是成本和安全问题,记得那时候我待的公司是做建站开发的,前 ...
- 一键式Spring集成工具 Spring Boot
最近公司使用Spring boot进行开发,稍微了解一下,不过自我感觉把集中式配置applicate.properties搞明白,注解用过Spring MVC的boot绝对没问题的 比如拦截器:@As ...
- Redis篇之操作、lettuce客户端、Spring集成以及Spring Boot配置
Redis篇之操作.lettuce客户端.Spring集成以及Spring Boot配置 目录 一.Redis简介 1.1 数据结构的操作 1.2 重要概念分析 二.Redis客户端 2.1 简介 2 ...
- 使用 docker 进行 ElasticSearch + Kibana 集群搭建
在Docker容器中运行Elasticsearch Kibana和Cerebro 机器信息 10.160.13.139 10.160.9.162 10.160.11.171 1. 安装docker和d ...
- Docker搭建ElasticSearch+Redis+Logstash+Filebeat日志分析系统
一.系统的基本架构 在以前的博客中有介绍过在物理机上搭建ELK日志分析系统,有兴趣的朋友可以看一看-------------->>链接戳我<<.这篇博客将介绍如何使用Docke ...
- docker+springboot+elasticsearch+kibana+elasticsearch-head整合(详细说明 ,看这一篇就够了)
一开始是没有打算写这一篇博客的,但是看见好多朋友问关于elasticsearch的坑,决定还是写一份详细的安装说明与简单的测试demo,只要大家跟着我的步骤一步步来,100%是可以测试成功的. 一. ...
随机推荐
- AMD Ryzen一代、二代CPU一览表
Ryzen一代(14纳米).二代(12纳米)CPU一览表 http://img30.360buyimg.com/sku/jfs/t1/1134/23/12713/382299/5bd910f9E63b ...
- opencart忘记登录密码怎么办
今天一位客户问opencart忘记登录密码怎么办,他们公司内部有几位员工同时在管理,可能是哪位同事把密码给改了没有跟大家说,现在都登录不了.这个只能数据库修改了.进入opencart的数据库,找到oc ...
- 09-C#笔记-循环
1. while 同 C++ 2. for 同 C++ 3. foreach,注意数组的定义 int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 ...
- JDOJ 2982: 最大连续子段和问题
洛谷 P1115 最大子段和 洛谷传送门 JDOJ 2982: 最大连续子段和问题 JDOJ传送门 题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入格式 第一行是一个正整数NN, ...
- Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1)
A. Alternating Sum 就是个等比数列,特判公比为 $1$ 的情况即可. #include <bits/stdc++.h> using namespace std; ; ; ...
- 深入js系列-类型(开篇)
思考 作为一个编程人员,你可能从来没仔细思考过,为什么这么多高级语言会有类型这东西. 实际上,类型有点类似生活中的类别,我们日常生活,早已经把这个概念理解到了,切肉和切水果会用不同的刀. 语言级别的类 ...
- C# 激活主窗口
今天同学跟我说了一个bug,虽然很简单,但还是记录一下,也好让我养成写东西的习惯. C# windows form 程序中,发生某个事件时,需要自动弹出一个窗口,提示用户,并等待用户输入进行处理. 如 ...
- Shell脚本之七 选择、循环结构
一.if else if 语法格式 if condition then command1 command2 ... commandN fi 写成一行(适用于终端命令提示符): if [ $(ps -e ...
- .net core mvc中input保留多位小数
本篇介绍:如何在mvc中使用html标签保留多位小数 你需要知道: @html标签的使用: https://blog.csdn.net/pasic/article/details/7093802 js ...
- pandas 获取不符合条件的dataframe
pandas 获取不符合条件的dataframe 或将其过滤掉: df[df["col"].str.contains('this'|'that')==False] >> ...