Elasticsearch简单查询与写入操作
自己的第一篇博客,简单记录下近期的一些小收获...
众所周知,Elasticsearch是一个高度可扩展的开源全文本搜索和分析引擎。它可以快速,近乎实时地存储,搜索和分析大量数据。它通常用作支持具有复杂搜索功能和要求的应用程序的基础引擎/技术,也是目前最火的分布式搜索框架。本文主要介绍关于版本为6.2.3(目前版本已更新到7.10)RestHighLevelClient的简单API操作,包括创建索引,判断索引是否存在,保存数据,查询数据等。
在项目中使用RestHighLevelClient进行操作,首先加载到spring容器中,也可以定义一个esConfig类,用于定义clusterName,nodes,socketTimeoutMillis,connectTimeoutMillis,maxConnectTotal等重要参数,这里就不列了
@Value("${elasticsearch.cluster-nodes}")
private String clusterNodes;
@Bean
public RestHighLevelClient restHighLevelClient() throws Exception{
ArrayList hostList = new ArrayList<>();
String[] nodes = clusterNodes.split(",");
for (String node : nodes) {
String[] parts = StringUtils.split(node, ":");
hostList.add(new HttpHost(parts[0], Integer.parseInt(parts[1])));
}
RestClientBuilder builder = RestClient.builder(hostList.toArray(new HttpHost[0]));
return new RestHighLevelClient(builder);
}
复制代码
创建索引
在项目启动时自动创建创建索引,类实现ApplicationRunner,然后重写run方法,将创建索引的逻辑写在里面即可
@Component
public class MyApplicationRunner implements ApplicationRunner{
private String indexName = "index_test";
@Override
public void run(ApplicationArguments args) throws Exception{
creatIndex();
}
/**
* 初始化创建操作日志索引
*/
private void creatIndex(){
esService.createIndex(logIndexName);
}
复制代码
public void createIndex(String indexName){
CreateIndexRequest request = new CreateIndexRequest(indexName);
// 定义别名
request.alias(new Alias("test"));
// 定义映射关系
XContentBuilder mapping = createMapping();
request.mapping("test", mapping);
// 创建索引
CreateIndexResponse createIndexResponse = esClient.indices().create(request);
}
private XContentBuilder createMapping(){
XContentBuilder mapping = null;
try {
mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject("properties")
.startObject("id").field("type", "keyword").endObject()
.startObject("name").field("type", "keyword").endObject()
.endObject()
.endObject();
} catch (Exception e) {
log.error("定义mapping异常", e);
}
return mapping;
}
复制代码
关于别名:这里简单说下,多个索引可以根据别名进行统一查询。例如按照月份存储log日志,存储时有log_202011,log_202012,log_202101等等,给他们设置统一别名,就叫log_all,查询log_all索引名称时就会查询该别名下的所有索引,当然,这里看看有没需要,因为我也不确定多个索引会不是导致性能变慢!(尴尬,还不会加图片,自行脑补苦笑表情)
判断索引是否存在
6.2.3版本判断索引与后续版本有所区别,项目时用的时候也遇到了一些小坑。
6.2.3版本可以使用open方法进行判断:
RestHighLevelClient client=new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http")));
OpenIndexRequest openIndexRequest = new OpenIndexRequest(indexName);
try {
client.indices().open(openIndexRequest);
return true;
} catch (Exception e) {
return false;
}
复制代码
另外,RestHighLevelClient还有个exists()方法,这个是判断该索引下是否有该条数据,这个是需要传入索引名称类型及id,与7.0X版本的indices().exists()不是不是一回事,注意不要搞混。
7.0X版本判断索引是否存在:
RestHighLevelClient client=new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http")));
GetIndexRequest exist=new GetIndexRequest("indexname");
boolean exists=client.indices().exists(exist, RequestOptions.DEFAULT);
复制代码
插入数据
这个就比较简单一点,话不多说,直接上代码
RestHighLevelClient esClient = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost",9200,"http")));
IndexRequest indexRequest = new IndexRequest("indexname", "indexType", "1");
// 第一个传入的参数为需要写入的json串,这里自行传入
indexRequest.source(jsonObject.toJSONString(), XContentType.JSON);
IndexResponse response = esClient.index(indexRequest);
复制代码
查询数据
实现mysql的like模糊查询功能
这里不能使用ik或者其他分词器,因为想要实现前后模糊的话,分词具有不确定性,不能保证前后模糊查出,这里有两种方式可供参考:
1.matchPhraseQuery + text组合 分词使用默认分词
match_phrase是分词的,text也是分词的。match_phrase的分词结果必须在text字段分词中都包含,而且顺序必须相同,而且必须都是连续的
2.wildcard{ "name": "* 测试 *"}
判断开始与结束时间
可使用QueryBuilders.rangeQuery进行时间的拼接
ps:如果es存储格式化的时间,存储的是UTC时间,转换时间戳时会存在8h的误差
eq 等于
neq 不等于
gt: greater than 大于
gte: greater than or equal 大于等于
lt: less than 小于
lte: less than or equal 小于等于
复制代码
这只是本人工作中使用的一点收获,如有错误,还请指正。我也是一个正在努力学习中的打工人!打工人,打工魂!望各位打工人可以实现自己的理想。
为了梦,学习吧!