SpringBoot下使用ElasticSearch教程(一)
一:ElasticSearch简单介绍.
ES是一款实时分析的分布式搜索引擎,易扩展集群,全文搜索,分布式实时文件存储,基于RESTful风格的简单易用API,底层使用Lucene封装,使用Java语言开发,和多种语言容易交互使用,速度非常快, 稳定,可靠,容易安装,开源.Lucene专注与底层搜索建设,ElasticSearch专注于企业应用.
ElasticSearch官网有非常详细的介绍:ElasticSearch.
ElasticSearch权威指南中文版:ElasticSearch中文版
二:环境准备.
我是方便测试,使用的Windows本地安装的ES,ES的安装教程比较多了,先把安装环境跑起吧.
ElasticSearch:6.4.1
SpringBoot:2.0.5.RELEASE
Maven
PostMan:接口测试工具,有json格式的数据校验,添加索引文章会比较方便的.
浏览器:Chrome
然后是安装好启动集群管理header插件.可以看到以正确启动了.
访问ES的集群面板.
使用PostMan添加索引.(说明一下,ES 6中,一个Index只能指定一个Type,亲测).下面是新建的Index.
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings":{
"novel":{
"properties":{
"word_count":{
"type":"integer"
},
"author":{
"type":"keyword"
},
"title":{
"type":"text"
},
"publish_date":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
}
}
}
}
}
新建索引指定id和自动生成id两种方式.
例如这里插入第一条吧.(PostMan),(发现字打错了如换成入吧,严谨一点吧.)
POST 127.0.0.1/book/novel/1
二:整合SpringBoot(仔细阅读注意一些不必要的坑 !!!).
新建一个SpringBoot项目.创建一下的目录.
pom.xml文件依赖如下.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lx.search</groupId>
<artifactId>elastic</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>elastic</name>
<description>ElasticSearch project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 引入ElasticSearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
<version>5.6.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
要引入那个transport-netty3-client的.否在报错哟.报错信息如下.
ES返回的文档对应实体对象,首先是完成实体类对象的编写吧.(如果觉得Set/Get麻烦,使用Lombok吧).
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import java.util.Date;
@Document(indexName = "book",type="novel")
public class Novel {
@Id
private Long id;
private String title;
private String author;
private Integer word_count;
private Date publish_data;
public Novel(){
super();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Integer getWord_count() {
return word_count;
}
public void setWord_count(Integer word_count) {
this.word_count = word_count;
}
public Date getPublish_data() {
return publish_data;
}
public void setPublish_data(Date publish_data) {
this.publish_data = publish_data;
}
@Override
public String toString() {
return "Novel{" +
"id=" + id +
", title='" + title + '\'' +
", author='" + author + '\'' +
", word_count=" + word_count +
", publish_data=" + publish_data +
'}';
}
}
接下来就是两种配置方式了.
方式一:ElasticsearchTemplate完成.(查看一下cluster_name,新增了一个默认的节点,就不是默认的elasticsearch了).
application.yml中的编写如下.
# 配置端口
server:
port: 8081
# 配置ElasticSearch
spring:
data:
elasticsearch:
cluster-nodes: 127.0.0.1:9300
cluster-name: my-application
repositories:
enabled: true
接下来就是完成查询了.(需求是查出所有带有word_count的书).
NovelController入下.
import com.lx.search.elastic.entity.Novel;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* title: com.lx.search.elastic.controller
* @author: lixing
* date: 2018/10/6 14:06
* description:查询小说吧
*/
@RestController
public class NovelController {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@RequestMapping("/search")
public String findDoc(){
// 构造搜索条件
QueryBuilder builder=QueryBuilders.existsQuery("word_count");
SearchQuery searchQuery=new NativeSearchQueryBuilder().withQuery(builder).build();
// 执行查询
List<Novel> novels=elasticsearchTemplate.queryForList(searchQuery,Novel.class);
for(Novel novel:novels){
System.out.println(novel);
}
return "Search Success";
}
}
在启动类的注解上添加包扫描.将实体类注入到容器成为Bean.
@SpringBootApplication(scanBasePackages = "com.lx.search.elastic")
启动访问一下吧:浏览器访问一下.
查看控制台如下:
id为null是说明数据类型不符合呗,直接修改为将id的类型修改String吧,ES自动和手动生成的id是String类型的.
修改为String类型后:
重新访问一下,问题解决.
方式二:TransportClient.
ElasticSearchConfig
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetAddress;
/**
* title: com.lx.search.elastic.config
* @author: lixing
* date: 2018/10/2 14:50
* description:ElasticSearchConfig的配置类
*/
@Configuration
public class ElasticSearchConfig {
private static final Logger logger = LoggerFactory.getLogger(ElasticSearchConfig.class);
@Bean
public TransportClient client() {
logger.info("初始化开始中...");
TransportClient client = null;
try {
TransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName("localhost"),
Integer.valueOf(9300));
// 配置信息
Settings esSetting = Settings.builder()
.put("cluster.name","my-application")
.build();
// 配置信息Settings自定义
client= new PreBuiltTransportClient(esSetting);
client.addTransportAddresses(transportAddress);
} catch (Exception e) {
logger.error("elasticsearch TransportClient create error!!!", e);
}
return client;
}
}
SaerchController.
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SearchController {
@Autowired
private TransportClient client;
@RequestMapping("/estest")
public void test(){
// 查询一条
GetResponse result=client.prepareGet("book","novel","1").get();
System.out.println(result);
}
}
浏览器访问一下:
控制台查看:(返回了id为1的json数据).
遇到问题如下:
2018-10-06 15:27:24.926 WARN 15064 --- [][generic][T#1]] o.e.c.t.TransportClientNodesService : node {#transport#-1}{Dv7dhgGlQCyxgGsSOd_JjQ}{localhost}{127.0.0.1:9300} not part of the cluster Cluster [elastic], ignoring...
控制台打印上述信息.
可以看出是节点名字错了吧,不是那个elastic.就进入到那个集群面板里面查看一下这个127.0.0.1:9300节点的cluster_name是那个
elastic吗???是默认的elasticsearch吗???,当然我是新建了节点的.
修改为my-application
再次重新启动一下,正常启动了,可以正常访问了.
三:简单总结.
在这次整合中也是遇到了问题,首先是自己认真的观察和仔细的思考一下,一步一步耐心解决吧.后面使用过程中在总结吧.