简单操作elasticsearch 7.4.2
1. 下载安装elasticsearch
1.1 用linux系统举例
-
直接去https://www.elastic.co/guide/index.html官网下载对应的系统文件
- copy到服务器或者虚拟机上 – 执行tar -zxvf elasticsearch.7.4.2.xxx进行压缩
- 进入到bin目录执行,./elasticsearch 启动,或者./elasticsearch -d后台启动
- 执行curl localhost:9200命令,如图所示,启动成功
1.2 用docker安装
- docker search elasticsearch:查询elasticsearch镜像
- docker pull elasticsearch:7.4.2:拉取elasticsearch 7.4.2版本的镜像
- docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e “discovery.type=single-node” IMAGEID 启动镜像,创建容器
- curl localhost:9200 :查看是否启动成功
2. elasticsearch安装时的一些常见错误
2.1 elasticsearch不能用root用户来运行
报错信息:org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException:can not run elasticsearch as root
adduser + username:创建用户;
su username:进入用户
2.2 新建用户没有权限的问题
报错信息:Exception in thread "main" java.nio.file.AccessDeniedException: /opt/dev/elasticsearch-7.4.2/config/jvm.options
由上图可知:我们不是root用户,但是启动的时候还是报错了,那是因为estest是我们新建的用户,我们还没有赋予他elasticsearch文件的权限
给用户权限:
chown -R estest /opt/dev/elasticsearch-7.4.2 // elasticsearch解压文件下的具体路径,一定要切换到root用户在给estest用户赋予权限
2.3 elasticsearch的jdk版本和装的jdk版本不匹配
报错信息:future versions of Elasticsearch will require Java 11; your Java version from [/usr/local/java/jdk1.8.0_181/jre] does not meet this requirement
// 因为我的elasticsearch是7.4.2版本的,所以需要jdk11以上,而我安装的jdk是1.8版本的,所以导致了错误
// elasticsearch现在是有内置jdk版本的,不需要安装jdk就可以直接执行
解决:进入elasticsearch-7.4.2/bin/下,修改elasticsearch文件
// 我看还有说是修改elasticsearch-env文件的,我还没有测试,有兴趣的小伙伴可以自己测试一下
export JAVA_HOME=/opt/dev/jdk11/jdk-11.0.10/
export PATH=$JAVA_HOME/bin:$PATH
if [ -x "$JAVA_HOME/bin/java" ]; then
JAVA="/opt/dev/jdk11/jdk-11.0.10/bin/java"
else
JAVA=`which java`
fi
2.4 垃圾回收机制被标记废弃问题
报错信息:Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
// 这个报错是告诉我们UseConcMarkSweepGC垃圾回收机器过时了,在未来可能被删除,我们要改成jdk11的垃圾回收机器
-XX:+UseG1GC
从上图我们可以看到,改过之后
Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
这个报错就被解决了 ==> 之前我一直以为是jdk指向问题,为此花费了大量时间,直到遇到一个在windows上安装elasticsearch运行的,才发现是这个问题,哭笑不得
2.5 elasticsearch占用内存问题
报错信息:Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000ca660000, 899284992, 0) failed; error='Not enough space' (errno=12)
还是修改jvm.options文件,一般把内存修改成512m就可以了
-Xms512m
-Xmx512m
2.6 未启动完成就请求curl localhost:9200报错
curl: (7) Failed to connect to ::1: No route to host
如图所示,我在启动之后报错,于是我去查看了一下日志,发现日志里面启动成功了。
// 服务启动时需要时间的,不可能你刚输出命令就可以访问的,报错我们去日志看一下就OK了
看过日志,我意识到,elasticsearch已经启动成功了,只是刚才还在启动中,所以访问出错,找不到主机;
我在curl localhost:9200一下,发现就可以了
3. elasticsearch的一些操作
3.1 localhost:9200/index/_search:查询index索引下的所有信息
3.2 http://localhost:9200/_cat/indices?v :查看所有索引
4. 用java代码实现elasticsearch
4.1 找到elasticsearch的api , 导入maven
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
当然我们这里用的是7.4.2版本的
4.2 设置springboot的elasticsearch版本为7.4.2,不然后面可能因版本不同而跑不起来
从上面的图中,我们可以看到我们springboot的elasticsearch是7.9.3版本的,而我们下载的是7.4.2版本的
为了版本对应,我们在pom.xml中设置elasticsearch版本为7.4.2
如图:我们可以看到,elasticsearch的版本修改成功,和我们下载的是一个版本了,接下来我们就可以配置启动了
4.3 写配置类连接我们的主机elasticsearch
@Bean
public RestHighLevelClient getEsClient() {
RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.146.129", 9200, "http"));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.146.129", 9200, "http")); // 连接主机
RestHighLevelClient client = new RestHighLevelClient(builder); // 操作elasticsearch 都靠RestHighLevelClient高级API
这样在执行的时候我可以直接调用 getEsClient();方法获取RestHighLevelClient来执行我们的elasticsearch操作
4.4 用代码操作elasticsearch
每个版本的API都是不一样的,如图所示可以找到指定的API版本教程
7.4 版本我使用的几个API
4.4.1 addIndex ==> 即Index API(单个add)
从图中我们可以看出,我们需要三个参数
-
Index索引
-
Id
-
source文档内容
source内容有三种方式存储,上图是第一种
第二种:已map键值对的方式存储
第三种:已实体类的方式存储(可以自定义任何实体类,存储的时候toJSONString)
// service方法
public String insert(String index , String id , IceResult result) throws Exception{
IndexRequest request = new IndexRequest(index);
request.id(id);
String jsonString = JSON.toJSONString(result.getData());
request.source(jsonString, XContentType.JSON); // elasticsearch的document内容
request.timeout("4s");
// 执行新增
RestHighLevelClient client = config.getEsClient();
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
return indexResponse.toString();
}
// controller方法
@RequestMapping(value = "/insert" , method = {RequestMethod.GET , RequestMethod.POST})
public String update(@RequestBody SupportContent obj) throws Exception {
SupportContent content = null;
if (IntUtil.isNotGreaterThanZero(obj.getId())) {
content = contentService.insert(obj);
} else {
content = contentService.updateByPrimaryKey(obj);
}
// 增加到数据库之后,新增到elasticsearch中
IceResult<SupportContent> result = new IceResult<>();
result.setData(content);
return build.insert("lezong" , content.getId().toString() , result);
}
// IceResult方法
public class IceResult<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
4.4.2 getIndex
GetRequest(index , id);
public GetResponse getIndex(String index , String id)throws Exception {
GetRequest getRequest = new GetRequest(index, id); // 传入index,id
RestHighLevelClient client = config.getEsClient(); // 获取RestHighLevelClient来执行搜索
return client.get(getRequest , RequestOptions.DEFAULT); // 执行查询
}
deleteRequest , updateRequest都是一样的操作
4.4.3 BulkAPI ==> BulkRequest 批量操作
批量增加
public boolean bulkIndex(String index , List<SupportContent> list) throws Exception {
BulkRequest request = new BulkRequest();
request.timeout("10m"); // 超时时间
list.forEach(e -> {
// 批量增加 index : 索引 , id:id , source : document文档数据
request.add(new IndexRequest(index).id(e.getId().toString())
.source(JSON.toJSONString(e) , XContentType.JSON));
});
// 执行
RestHighLevelClient client = config.getEsClient();
BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);
return !bulk.hasFailures();
}
同时增加,修改,删除操作
4.4.4 searchAPI ==> 指定检索
SearchSourceBuilder是检索参数:包括请求超时时间,检索多少条,从什么位置开始检索等等
// 建立检索
SearchRequest searchRequest = new SearchRequest(index);
// 检索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 精准搜索条件 -- fieldName:elasticsearch中的document文件
MatchQueryBuilder query = new MatchQueryBuilder("content", keyword);
// QueryBuilder query = QueryBuilders.matchQuery("content", keyword);
// TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("user", "kimchy"); // 经试验,这个检索在我的机器上并不能用
if (StringUtil.isTrimBlank(keyword)) {
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 不指定查询,查询index中全部内容
}
// 其他查询条件
searchSourceBuilder.from(page); // 从page开始
searchSourceBuilder.size(pageSize); // 查询pageSize条数据
searchSourceBuilder.query(query);
searchSourceBuilder.timeout(new TimeValue(60 , TimeUnit.MINUTES)); // 设置超时时间
// 执行搜索
searchRequest.source(searchSourceBuilder);
RestHighLevelClient client = config.getEsClient();
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
// 解析结果
List<Map<String , Object>> list = new ArrayList<>();
SearchHit[] hits = search.getHits().getHits();
for (SearchHit hit : hits) {
list.add(hit.getSourceAsMap());
}
return list;
4.4.5 Multi-Search
public List<Map<String , Object>> multiSearch(String index , String keyWord , String columns)throws Exception {
// index:索引 , keyWord:检索关键字 , columns:document中source字段
// 其实就是做了一个封装,条件还是上面的SearchRequest
MultiSearchRequest request = new MultiSearchRequest();
// 循环放入查询条件
for (String column : columns.split(",")) {
SearchRequest firstSearchRequest = new SearchRequest();
// 若没告诉查哪个索引,则查全部索引
if (StringUtil.isNotTrimBlank(index)) {
firstSearchRequest.indices(index);
}
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery(column , keyWord));
firstSearchRequest.source(searchSourceBuilder);
request.add(firstSearchRequest);
}
// 执行查询
RestHighLevelClient client = config.getEsClient();
MultiSearchResponse msearch = client.msearch(request, RequestOptions.DEFAULT);
List<Map<String , Object>> list = new ArrayList<>();
MultiSearchResponse.Item[] responses = msearch.getResponses();
for (MultiSearchResponse.Item item : responses) {
SearchResponse response = item.getResponse();
SearchHits hits = response.getHits();
SearchHit[] hits1 = hits.getHits();
for (SearchHit hit : hits1) {
list.add(hit.getSourceAsMap());
}
}
return list;
}
// controller层
@GetMapping(value = "/multiSearch")
public List<Map<String, Object>> multiSearch(String keyWord , String columns , String index)throws Exception {
if (StringUtil.isTrimBlank(index)) {
index = "roots";
}
return build.multiSearch(index, keyWord, columns); // 我columns中传的为title,content
}
// 注意,multiSearchRequest中的QueryBuilders是有先后顺序的 , 可以自己调换一个columns中的字段先后顺序试一下
// 例:有字段,title,content,name的先后顺序,则他会检索title中匹配的放在前面,在检索content中匹配的紧接着,最后会把从name中检索匹配的放在最后
st;
}
// controller层
@GetMapping(value = “/multiSearch”)
public List<Map<String, Object>> multiSearch(String keyWord , String columns , String index)throws Exception {
if (StringUtil.isTrimBlank(index)) {
index = “roots”;
}
return build.multiSearch(index, keyWord, columns); // 我columns中传的为title,content
}
// 注意,multiSearchRequest中的QueryBuilders是有先后顺序的 , 可以自己调换一个columns中的字段先后顺序试一下
// 例:有字段,title,content,name的先后顺序,则他会检索title中匹配的放在前面,在检索content中匹配的紧接着,最后会把从name中检索匹配的放在最后