1. 前提
网上学习Elasticsearch教程很多,但是有的不是那么完善,会有很多坑,做一些记录,方便后面自己查找,回顾。附上代码可以正常运行。
1. 使用版本
- Elasticsearch: 7.9.1
- Kibana: 7.9.1
- elasticsearch-head-master
注:window上安装参考:windows安装es+kibana
2. 对比
mysql | Elasticsearch |
---|---|
database | Indices |
Tables | Types |
rows | Documents |
columns | Fields |
3.常见问题
- 报错:Caused by: NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{192.168.1.105}{192.168.1.105:9300}]]
这个问题就是版本不对,不管你怎么设置也好 ,始终就会出这个问题。
- 版本对应关系
- Elasticsearch 和 kibana 版本要统一,不然无法启动
- 配置文件中的name 要和Elasticsearch 中 yml文件的cluster-name对应
2. 代码说明
代码是用了多种方式实现查询功能,感兴趣的朋友可以继续往下写
- 采用ElasticsearchRepository下的JPA实现查询功能,此方法不是很全,方法是继承ElasticsearchRepository<User, String>,然后写部分功能
- 采用SearchSourceBuilder实现查询
步骤:- 构建查询条件
- SearchSourceBuilder进行封装
- 创建并设置SearchRequest对象,SearchRequest searchRequest = new SearchRequest("userindex); 匹配索引 如果不指定 自动匹配
- client进行查询
- 使用JSON转换成实体,User user = JSON.parseObject(JSON.toJSONString(hit.getSourceAsMap()), User.class);
- 自定义查询方式,方式灵活多样。包括多种查询,单一匹配,多匹配,范围查询等
- 测试用例:
{"id":1,"name":"张三","age":18,"description":"张三是java开发工程师","createtm": "2020-9-30 10:01:32"}
- 请求示例:
http://127.0.0.1:8281/test/searchByMoreUseSearch?searchContent=张
3. 具体代码
github地址:项目地址
pom文件
<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>1.0.0</groupId>
<artifactId>springboot-elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<packaging>jar</packaging>
<name>springboot-elasticsearch</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<springBoot>2.3.1.RELEASE</springBoot>
<jest.version>5.3.3</jest.version>
</properties>
<dependencies>
<!-- Spring Boot Elasticsearch 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${springBoot}</version>
</dependency>
<!--Jest工具包 -->
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>${jest.version}</version>
</dependency>
<!-- Spring Boot Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springBoot}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<version>${springBoot}</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
</dependencies>
</project>
controller
package com.rain.test.controller;
import java.util.List;
import com.rain.test.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.rain.test.service.UserService;
/**
*
* @Title: UserRestController
* @Description:
* es基础学习
* @author Rain
* @date 2020年9月30日
*/
@RestController
@RequestMapping(value = "/test")
public class UserRestController {
@Autowired
private UserService userService;
@PostMapping("/createUser")
public boolean createUser(@RequestBody User user) {
return userService.createUser(user);
}
@GetMapping("/searchAll")
public List<User> searchAll() {
return userService.searchAll();
}
@GetMapping("/searchContent")
public List<User> searchContent(@RequestParam(value = "searchContent") String searchContent) {
return userService.searchContent(searchContent);
}
@GetMapping("/searchByName")
public List<User> searchByName(@RequestParam(value = "searchContent") String searchContent) {
return userService.searchByName(searchContent);
}
@GetMapping("/searchByUserAge")
public List<User> searchByUserAge(@RequestParam(value = "age") Integer age) {
return userService.searchByUserAge(age);
}
@GetMapping("/searchByMoreUseQuery")
public List<User> searchByMoreUseQuery(@RequestParam(value = "searchContent") String searchContent) {
return userService.esSearchByMore(searchContent);
}
@GetMapping("/searchByMoreUseSearch")
public List<User> searchByMoreUseSearch(@RequestParam(value = "searchContent") String searchContent) {
return userService.searchByMoreUseSearch(searchContent);
}
@GetMapping("/searchByMoreContent")
public List<User> searchByMoreContent(@RequestParam(value = "name") String name,@RequestParam(value = "description") String description) {
return userService.searchByMoreContent(name, description);
}
@GetMapping("/searchByRange")
public List<User> searchByRange(Integer age) {
return userService.searchByRange(age);
}
}
dao
package com.rain.test.dao;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.rain.test.pojo.User;
import java.util.*;
/**
* @author Rain
*/
public interface UserDao extends ElasticsearchRepository<User, String>{
List<User> getAllBy();
List<User> queryUserByAge(Integer age);
}
pojo
package com.rain.test.pojo;
import java.io.Serializable;
import org.springframework.data.elasticsearch.annotations.Document;
/**
* @author xiayu
*/
@Document(indexName = "userindex", type = "user")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/** 编号 */
private String id;
/** 姓名 */
private String name;
/** 年龄 */
private Integer age;
/** 描述 */
private String description;
/** 创建时间 */
private String createtm;
public User(){
}
public User(String id, String name, Integer age, String description, String createtm) {
super();
this.id = id;
this.name = name;
this.age = age;
this.description = description;
this.createtm = createtm;
}
/**
* 获取编号
* @return id
*/
public String getId() {
return id;
}
/**
* 设置编号
* @param id
*/
public void setId(String id) {
this.id = id;
}
/**
* 获取姓名
* @return name
*/
public String getName() {
return name;
}
/**
* 设置姓名
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取年龄
* @return age
*/
public Integer getAge() {
return age;
}
/**
* 设置年龄
* @param age
*/
public void setAge(Integer age) {
this.age = age;
}
/**
* 获取描述
* @return description
*/
public String getDescription() {
return description;
}
/**
* 设置描述
* @param description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* 获取创建时间
* @return createtm
*/
public String getCreatetm() {
return createtm;
}
/**
* 设置创建时间
* @param createtm
*/
public void setCreatetm(String createtm) {
this.createtm = createtm;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", description=" + description + ", createtm="
+ createtm + "]";
}
}
service
package com.rain.test.service;
import java.util.List;
import com.rain.test.pojo.User;
/**
*
* Title: UserService
* @author Rain
* @date 2020年9月30日
*/
public interface UserService {
/**
* 新增用户信息
*
* @param user
* @return
*/
boolean createUser(User user);
/**
* 根据关键字进行全文搜索
* @param searchContent
* @return
*/
List<User> searchContent(String searchContent);
/**
* 查询全部
*
* @return
*/
List<User> searchAll();
/**
* 根据关键词权重进行查询
* @param searchContent
* @return
*/
List<User> searchByName(String searchContent);
/**
* 年龄查询
*
* @param age
* @return
*/
List<User> searchByUserAge(Integer age);
/**
* 多条件查询
*
* @param searchContent
* @return
*/
List<User> esSearchByMore(String searchContent);
/**
* 多条件匹配查询
*
* @param name
* @param description
* @return
*/
List<User> searchByMoreContent(String name, String description);
/**
* 使用searchSource多匹配查询
*
* @param searchContent
* @return
*/
List<User> searchByMoreUseSearch(String searchContent);
/**
* 根据范围查询
*
* @param age
* @return
*/
List<User> searchByRange(Integer age);
}
sevice Impl
package com.rain.test.service.impl;
import java.io.IOException;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.rain.test.dao.UserDao;
import com.rain.test.pojo.User;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.rain.test.service.UserService;
import java.util.*;
/**
* @author Rain
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private RestHighLevelClient client;
@Override
public boolean createUser(User user) {
boolean flag = false;
try{
userDao.save(user);
flag=true;
}catch(Exception e){
e.printStackTrace();
}
return flag;
}
@Override
public List<User> searchContent(String searchContent) {
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(searchContent);
System.out.println("查询的语句:"+builder);
Iterable<User> searchResult = userDao.search(builder);
List<User> list= Lists.newArrayList(searchResult);
return list;
}
@Override
public List<User> searchAll() {
return userDao.getAllBy();
}
@Override
public List<User> searchByName(String searchContent) {
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(QueryBuilders.matchQuery("name", searchContent));
System.out.println("查询的语句:" + functionScoreQueryBuilder.toString());
Iterable<User> searchResult = userDao.search(functionScoreQueryBuilder);
List<User> list= Lists.newArrayList(searchResult);
return list;
}
@Override
public List<User> searchByUserAge(Integer age) {
return userDao.queryUserByAge(age);
}
@Override
public List<User> esSearchByMore(String searchContent) {
// 多个匹配
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchContent, "name", "description");
System.out.println("查询的语句:" + multiMatchQueryBuilder.toString());
Iterable<User> searchResult = userDao.search(multiMatchQueryBuilder);
return Lists.newArrayList(searchResult);
}
@Override
public List<User> searchByMoreContent(String name, String description) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("name", name))
.must(QueryBuilders.termQuery("description", description));
Iterable<User> userIterable = userDao.search(queryBuilder);
return Lists.newArrayList(userIterable);
}
@Override
public List<User> searchByMoreUseSearch(String searchContent) {
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchContent, "name", "description");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(multiMatchQueryBuilder);
// 创建并设置SearchRequest对象
// SearchRequest searchRequest = new SearchRequest("userindex); 匹配索引 如果不指定 自动匹配
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest,RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<User> userList = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
User user = JSON.parseObject(JSON.toJSONString(hit.getSourceAsMap()), User.class);
userList.add(user);
}
return userList;
}
@Override
public List<User> searchByRange(Integer age) {
//包括下界 包括上界
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age")
.from(20).to(age)
.includeLower(true).includeUpper(false);
Iterable<User> userIterable = userDao.search(rangeQueryBuilder);
return Lists.newArrayList(userIterable);
}
}
启动类
package com.rain.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.SpringVersion;
/**
* @author Rian
*/
@SpringBootApplication
public class ElasticSearchApp
{
public static void main( String[] args )
{
// 启动嵌入式的 Tomcat 并初始化 Spring 环境及其各 Spring 组件
SpringApplication.run(ElasticSearchApp.class, args);
System.out.println("ElasticSearch 程序正在运行...");
String version = SpringVersion.getVersion();
String version1 = SpringBootVersion.getVersion();
System.out.println(version);
System.out.println(version1);
}
}
配置文件
server:
port: 8281
spring:
banner:
charset: utf-8
application:
name: springboot2-elasticsearch
http:
encoding:
charset: utf-8
enabled: true
force: true
messages:
encoding: UTF-8
data:
elasticsearch:
repositories:
enabled: true
cluster-nodes: localhost:9300
cluster-name: my-application