SpringBoot整合ElasticSearch实现多版本的兼容

SpringBoot整合ElasticSearch实现多版本的兼容
前⾔
在学习SpringBoot中,整合了Mybatis、Druid和PageHelper并实现了多数据源的操作。本篇主要是介绍和使⽤⽬前最⽕的搜索引擎ElastiSearch,并和SpringBoot进⾏结合使⽤。
ElasticSearch介绍
ElasticSearch是⼀个基于Lucene的搜索服务器,其实就是对Lucene进⾏封装,提供了 REST API 的操作接⼝ ElasticSearch作为⼀个⾼度可拓展的开源全⽂搜索和分析引擎,可⽤于快速地对⼤数据进⾏存储,搜索和分析。
ElasticSearch主要特点:分布式、⾼可⽤、异步写⼊、多API、⾯向⽂档。
ElasticSearch核⼼概念:近实时,集,节点(保存数据),索引,分⽚(将索引分⽚),副本(分⽚可设置多个副本)。它可以快速地储存、搜索和分析海量数据。
ElasticSearch使⽤案例:、Stack Overflow、Github 等等。
SpringBoot整合Elasticsearch
在使⽤SpringBoot整合Elasticsearch 之前,我们应该了解下它们之间的关系。
Spring Boot Version (x)Spring Data Elasticsearch Version (y)Elasticsearch Version (z)
x <= 1.3.5y <= 1.3.4z <= 1.7.2*
x >= 1.4.x  2.0.0 <=y < 5.0.0**  2.0.0 <= z < 5.0.0**
这⾥我们使⽤的SpringBoot的版本是1.5.9,Elasticsearch的版本是2.3.5。
使⽤SpringBoot整合Elasticsearch,⼀般都是使⽤ SpringData 进⾏封装的,然后再dao层接⼝继承ElasticsearchRepository 类,该类实现了很多的⽅法,⽐如常⽤的CRUD⽅法。
SpringData的使⽤
⾸先,在使⽤之前,先做好相关的准备。
Maven的配置如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
application.properties的配置
spring.abled = true
spring.data.elasticsearch.cluster-nodes =127.0.0.1\:9300
注: 9300 是 Java 客户端的端⼝。9200 是⽀持 Restful HTTP 的接⼝。
更多的配置:
spring.data.elasticsearch.cluster-name Elasticsearch 集名。(默认值: elasticsearch)
spring.data.elasticsearch.cluster-nodes 集节点地址列表,⽤逗号分隔。如果没有指定,就启动⼀个客户端节点。
spring.data.elasticsearch.propertie ⽤来配置客户端的额外属性。
spring.abled 开启 Elasticsearch 仓库。(默认值:true。)
代码编写
实体类
@Document(indexName = "userindex", type = "user")
public class User implements Serializable{
阿拉蕾眼镜/**
*
*/
private static final long serialVersionUID = 1L;
/** 编号 */
private Long id;
/** 姓名 */
private String name;
/** 年龄 */
private Integer age;
/** 描述 */
private String description;
/
** 创建时间 */
private String createtm;
// getter和setter 略
使⽤SpringData的时候,它需要在实体类中设置indexName 和type ,如果和传统型数据库⽐较的话,就相当于库和表。需要注意的是indexName和type都必须是⼩写
dao层
public interface UserDao extends ElasticsearchRepository<User, Long>{
}
dao层这⾥就⽐较简单了,只需继承ElasticsearchRepository该类就⾏了。其中主要的⽅法就是 save、delete和search。其中save⽅法相当如insert和update,没有就新增,有就覆盖。delete⽅法主要就是删除数据以及索引库。⾄于search就是查询了,包括⼀些常⽤的查询,如分页、权重之类的。
Service层
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean insert(User user) {
gn205
boolean falg=false;
try{
falg=true;
}catch(Exception e){
e.printStackTrace();
}
return falg;
}
@Override
public List<User> search(String searchContent) {
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent);
System.out.println("查询的语句:"+builder);bevix
Iterable<User> searchResult = userDao.search(builder);
Iterator<User> iterator = searchResult.iterator();
List<User> list=new ArrayList<User>();
笨笨牛历险记
while (iterator.hasNext()) {
list.());
}
return list;
}
@Override
public List<User> searchUser(Integer pageNumber, Integer pageSize,String searchContent) {
// 分页参数
Pageable pageable = new PageRequest(pageNumber, pageSize);
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent);
SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(builder).build();
System.out.println("查询的语句:" + Query().toString());
Page<User> searchPageResults = userDao.search(searchQuery);
Content();
}
@Override
public List<User> searchUserByWeight(String searchContent) {
// 根据权重进⾏查询
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name", searchContent)),
ScoreFunctionBuilders.weightFactorFunction(10))
.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("description", searchContent)),
ScoreFunctionBuilders.weightFactorFunction(100)).setMinScore(2);
System.out.println("查询的语句:" + String());
Iterable<User> searchResult = userDao.search(functionScoreQueryBuilder);
Iterator<User> iterator = searchResult.iterator();
List<User> list=new ArrayList<User>();
while (iterator.hasNext()) {
list.());
}
return list;
}
}
这⾥我就简单的写了⼏个⽅法,其中主要的⽅法是查询。查询包括全⽂搜索,分页查询和权重查询。其中需要说明的是权重查询这块,权重的分值越⾼,查询的结果也越靠前,如果没有对其它的数据设置分值,它们默认的分值就是1,如果不想查询这些语句,只需使⽤setMinScore将其设为⼤于1即可。
代码测试
调⽤接⼝进⾏添加数据
新增数据:
POST localhost:8086/api/user
{"id":1,"name":"张三","age":20,"description":"张三是个Java开发⼯程师","createtm":"2018-4-25 11:07:42"}
{"id":2,"name":"李四","age":24,"description":"李四是个测试⼯程师","createtm":"1980-2-15 19:01:32"}
{"id":3,"name":"王五","age":25,"description":"王五是个运维⼯程师","createtm":"2016-8-21 06:11:32"}
进⾏全⽂查询
请求
localhost:8086/api/user?searchContent=⼯程师
返回
[{"id":2,"name":"李四","age":14,"description":"李四是个测试⼯程师","createtm": "1980-2-15 19:01:32"},
{"id":1,"name":"张三","age":20,"description":"张三是个Java开发⼯程师", "createtm": "2018-4-25 11:07:42"},
{"id":3,"name":"王五","age":25,"description":"王五是个运维⼯程师","createtm": "2016-8-21 06:11:32"}]
进⾏分页查询
请求
localhost:8086/api/user?pageNumber=0&pageSize=2&searchContent=⼯程师
返回
[{"id":2,"name":"李四","age":14,"description":"李四是个测试⼯程师"},{"id":1,"name":"张三","age":20,"description":"张三是个Java开发⼯程师"}]
进⾏权重查询
请求
localhost:8086/api/user2?searchContent=李四
返回
[{"id":2,"name":"李四","age":24,"description":"李四是个测试⼯程师","createtm":"1980-2-15 19:01:32"}]
权重查询打印的语句:
查询的语句:{{
"function_score" : {
"functions" : [ {
"filter" : {
"bool" : {
"should" : {
"match" : {
"name" : {
"query" : "李四",
"type" : "boolean"
}
}
}
}
},
"weight" : 10.0
}, {
"filter" : {
"bool" : {
"should" : {
"query" : "李四",
"type" : "boolean"
}
}
}
}
},
"weight" : 100.0
} ],
"min_score" : 2.0
}
}
注:测试中,因为设置了setMinScore最⼩权重分为2的,所以⽆关的数据是不会显⽰出来的。如果想显⽰的话,在代码中去掉即可。
新增完数据之后,可以在浏览器输⼊:
然后点击基本查询,便可以查看添加的数据。如果想⽤语句查询,可以将程序中控制台打印的查询语句粘贴到查询界⾯上进⾏查询!
注:这⾥的ElasticSearch是我在windows上安装的,并安装了ES插件head,具体安装步骤在⽂章末尾。
除了SpringData之外,其实还有其它的⽅法操作ElasticSearch的。
⽐如使⽤原⽣ElasticSearch的Api,使⽤TransportClient类实现。
或者使⽤由Spring封装,只需在Service层,进⾏注⼊Bean即可。
⽰例:
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
但是,上述⽅法中都有其局限性,也就是随着ElasticSearch的版本变更,相关的Java API也在做不断的调整,就是ElasticSearch服务端版本进⾏更改之后,客户端的代码可能需要重新编写。
因此介绍⼀个相当好⽤的第三⽅⼯具JestClient,它对ElasticSearch进⾏封装,填补了 ElasticSearch HttpRest接⼝客户端的空⽩,它适⽤于ElasticSearch2.x以上的版本,⽆需因为ElasticSearch服务端版本更改⽽对代码进⾏更改!
JestClient
⾸先在Maven中添加如下依赖:
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.3</version>
</dependency>
然后编写相关的测试代码。
代码中的注释应该很完整,所以这⾥就不再对代码过多的讲述了。
import java.util.ArrayList;
import java.util.List;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import com.pancm.pojo.User;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.JestResult;
import io.fig.HttpClientConfig;
import Bulk;
import BulkResult;
import Delete;
import DocumentResult;
import Index;
import Search;
import io.searchbox.indices.CreateIndex;
import io.searchbox.indices.DeleteIndex;
import io.searchbox.indices.mapping.GetMapping;
import io.searchbox.indices.mapping.PutMapping;
public class JestTest {
private static JestClient jestClient;
private static String indexName = "userindex";
//    private static String indexName = "userindex2";
private static String typeName = "user";
private static String elasticIps="192.169.2.98:9200";
//    private static String elasticIps="127.0.0.1:9200";
public static void main(String[] args) throws Exception {
jestClient = getJestClient();
insertBatch();
serach1();
serach2();
serach3();
jestClient.close();
}
private static  JestClient getJestClient() {
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig.Builder(elasticIps).connTimeout(60000).readTimeout(60000).multiThreaded(true).build());
Object();
}
public static void insertBatch() {
List<Object> objs = new ArrayList<Object>();
objs.add(new User(1L, "张三", 20, "张三是个Java开发⼯程师","2018-4-25 11:07:42"));
try {
result = insertBatch(jestClient,indexName, typeName,objs);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("批量新增:"+result);
}
/**
* 全⽂搜索
*/
public static void serach1() {
String query ="⼯程师";
try {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.queryStringQuery(query));
//分页设置
searchSourceBuilder.from(0).size(2);
System.out.println("全⽂搜索查询语句:"+String());
System.out.println("全⽂搜索返回结果:"+search(jestClient,indexName, typeName, String()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 精确搜索
*/
public static void serach2() {
try {
西安医学院第一附属医院SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.Query("age", 24));
System.out.println("精确搜索查询语句:"+String());
System.out.println("精确搜索返回结果:"+search(jestClient,indexName, typeName, String()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 区间搜索
*/
public static void serach3() {
String createtm="createtm";
String from="2016-8-21 06:11:32";
String to="2018-8-21 06:11:32";
try {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.rangeQuery(createtm).gte(from).lte(to));
System.out.println("区间搜索语句:"+String());
System.out.println("区间搜索返回结果:"+search(jestClient,indexName, typeName, String()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建索引
* @param indexName
* @return
* @throws Exception
*/
public boolean createIndex(JestClient jestClient,String indexName) throws Exception {
JestResult jr = ute(new CreateIndex.Builder(indexName).build());
return jr.isSucceeded();
}
/**
* 新增数据
* @param indexName
* @param typeName
缺陷者捧出的花束* @param source
* @return
* @throws Exception
*/
public boolean insert(JestClient jestClient,String indexName, String typeName, String source) throws Exception {
PutMapping putMapping = new PutMapping.Builder(indexName, typeName, source).build();
JestResult jr = ute(putMapping);
return jr.isSucceeded();
}
/**
* 查询数据
* @param indexName
* @param typeName
* @return
* @throws Exception
*/
public static String getIndexMapping(JestClient jestClient,String indexName, String typeName) throws Exception {
GetMapping getMapping = new GetMapping.Builder().addIndex(indexName).addType(typeName).build();
JestResult jr =ute(getMapping);
JsonString();
}
/**
* 批量新增数据
* @param indexName
* @param typeName
* @param objs
* @return
* @throws Exception
*/
public static boolean insertBatch(JestClient jestClient,String indexName, String typeName, List<Obje
ct> objs) throws Exception {          Bulk.Builder bulk = new Bulk.Builder().defaultIndex(indexName).defaultType(typeName);
for (Object obj : objs) {
Index index = new Index.Builder(obj).build();
bulk.addAction(index);
}
BulkResult br = ute(bulk.build());
return br.isSucceeded();
}
/**
* @param query
* @return
* @throws Exception
*/
public static String search(JestClient jestClient,String indexName, String typeName, String query) throws Exception {
Search search = new Search.Builder(query)
.addIndex(indexName)
.addType(typeName)
.build();
JestResult jr = ute(search);
//        System.out.println("--"+jr.getJsonString());
//        System.out.println("--"+jr.getSourceAsObject(User.class));
SourceAsString();
}
/**
* 删除索引
* @param indexName
* @return
* @throws Exception
*/
public boolean delete(JestClient jestClient,String indexName) throws Exception {
JestResult jr = ute(new DeleteIndex.Builder(indexName).build());
return jr.isSucceeded();
}
/
**
* 删除数据
* @param indexName
* @param typeName
* @param id
* @return
* @throws Exception
*/
public boolean delete(JestClient jestClient,String indexName, String typeName, String id) throws Exception {
DocumentResult dr = ute(new Delete.Builder(id).index(indexName).type(typeName).build());
return dr.isSucceeded();
}
注:测试之前先说明下,本地windows系统安装的是ElasticSearch版本是2.3.5,linux服务器上安装的ElasticSearch版本是6.2。
测试结果
全⽂搜索
全⽂搜索查询语句:{
"from" : 0,
"size" : 2,
"query" : {
"query_string" : {
"query" : "⼯程师"
}
}
}
全⽂搜索返回结果:{"id":1,"name":"张三","age":20,"description":"张三是个Java开发⼯程师","createtm":"2018-4-25 11:07:42"},{"id":2,"name":"李四","age":24,"description":"李四是个测试⼯程师","createtm":"1980-2-15 19:01:32"}匹配搜索
精确搜索查询语句:{
"query" : {
"term" : {
"age" : 24
}
}
}
精确搜索返回结果:{"id":2,"name":"李四","age":24,"description":"李四是个测试⼯程师","createtm":"1980-2-15 19:01:32"}
时间区间搜索
区间搜索语句:{
"query" : {
"range" : {
"createtm" : {
"from" : "2016-8-21 06:11:32",
"to" : "2018-8-21 06:11:32",
"include_lower" : true,
"include_upper" : true
}
}
}
}
区间搜索返回结果:{"id":1,"name":"张三","age":20,"description":"张三是个Java开发⼯程师","createtm":"2018-4-25 11:07:42"}
新增完数据之后,我们可以上linux的 Kibana中进⾏相关的查询,查询结果如下:

本文发布于:2024-09-20 17:45:36,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/523481.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:查询   搜索   数据   语句   版本   代码
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议