前言
elasticsearch基本介绍,这篇文章介绍了elasticsearch安装和使用。下面根据网上查来的各种资料,总结如何在springboot中使用elasticsearch。
文章中用es代替elasticsearch。
依赖
springboot版本是2.0,es版本用的是7.6.2。不同的springboot版本对应不同的es版本。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
application.yml
在配置文件中指定es的ip和端口。es默认端口是9200
spring:
elasticsearch:
rest:
uris: http://127.0.0.1:9200
实体类
在实体类中通过注解指定索引名称、分片数、备份数等
@Document(indexName = "article_index",shards = 5,replicas = 1)
public class Article {
@Id
@Field(type = FieldType.Long,store = true)
private long id;
@Field(type = FieldType.Text,store = true,analyzer = "ik_min_word")
private String auth;
@Field(name = "book_title",type = FieldType.Text,store = true,analyzer = "ik_max_word")
private String bookTitle;
@Field(type = FieldType.Text,store = true,analyzer = "ik_max_word")
private String content;
public Article() {
}
// get set
es的命名规范中不可以使用大写,所以当属性名由两个单词组成时,java使用驼峰命名法,es使用下划线命名法,在@Field注解中使用name进行命名区分
数据层
@Mapper
public interface ArticleDao {
/**
* 查询全部数据
*/
List<Article> queryAllArticle();
/**
* 修改数据
*/
void updateArticle(Map map);
}
ElasticsearchRepository接口
自定义接口需要继承ElasticsearchRepository接口,接口方法命名规则类似spring data jpa,无需实现具体接口方法。
如果不知道spring data jpa是什么,点这个链接
public interface ArticleRepositories extends ElasticsearchRepository<Article,Long> {
/**
* 根据标题查询
*/
List<Article> findArticlesByBookTitle(String title);
/**
* 根据作者查询
*/
List<Article> findArticlesByAuth(String auth);
/**
* 根据内容查询
*/
List<Article> findArticlesByContent(String content);
/**
* 根据标题或者内容查询
*/
List<Article> findArticlesByBookTitleOrContent(String title,String content);
/**
* 根据标题或者内容查询 分页
*/
List<Article> findArticlesByBookTitleOrContent(String title, String content, Pageable pageable);
/**
* 根据作者以及标题查询
*/
List<Article> findByAuthAndBookTitle(String auth,String title);
/**
* 根据作者以及标题查询 分页
*/
List<Article> findByAuthAndBookTitle(String auth,String title,Pageable pageable);
}
启动类
@SpringBootApplication
public class StartElasticSearchApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(StartElasticSearchApplication.class, args);
}
}
测试类
测试类中需要注入ArticleRepositories和ElasticsearchRestTemplate。导入类时需要包路径,不要导错了
import com.ela.StartElasticSearchApplication;
import com.ela.dao.ArticleDao;
import com.ela.pojo.Article;
import com.ela.repositories.ArticleRepositories;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = StartElasticSearchApplication.class)
public class TestEs {
@Autowired
private ArticleRepositories articleRepositories;
@Autowired
private ElasticsearchRestTemplate template;
}
创建索引并插入数据
添加文档时如果索引库不存在则会自动创建
@Test
public void addDocument() throws Exception{
// 直接从数据库中查询数据
List<Article> articles = articleDao.queryAllArticle();
for (Article article : articles) {
// 将查询到的数据依次写入索引中
articleRepositories.save(article);
}
}
执行完后使用kibana查询添加的文档
GET /article_index/_search
{
"from": 0,
"size": 30,
"sort": [
{
"id": {
"order": "asc"
}
}
]
}
删除文档
@Test
public void deleteDocument(){
// 根据id删除
//articleRepositories.deleteById(1l);
// 删除全部
articleRepositories.deleteAll();
}
查询所有文档
@Test
public void findAll(){
Iterable<Article> articles = articleRepositories.findAll();
for (Article article : articles) {
System.out.println(article.toString());
}
}
执行结果
根据id查询
@Test
public void findById(){
// 根据id查询
Article article = template.get("14", Article.class);
System.out.println(article);
}
根据标题查询
查询标题中带有“悲剧”两个字的数据
@Test
public void findByTitle(){
List<Article> articles = articleRepositories.findArticlesByTitle("悲剧");
for (Article article : articles) {
System.out.println(article.toString());
}
}
根据作者查询
查询作者名字带“东”和“吾”两个字的数据
@Test
public void findByAuth(){
List<Article> articles = articleRepositories.findArticlesByAuth("东吾");
for (Article article : articles) {
System.out.println(article.toString());
}
}
根据作者和标题查询
@Test
public void findByAuthTitle(){
List<Article> articleList = articleRepositories.findByAuthAndTitle("埃因", "悲剧");
for (Article article : articleList) {
System.out.println(article.toString());
}
System.out.println("------分页-------");
// 分页
Pageable pageable = PageRequest.of(0,2);
List<Article> articleList2 = articleRepositories.findByAuthAndTitle("埃因", "悲剧",pageable);
for (Article article : articleList2) {
System.out.println(article.toString());
}
}
使用PageRequest.of(0,2)进行分页,其中第一个参数表示页码,第二个参数表示一页中包含几条数据。需注意,第一个参数为0时表示第1页、为1时表示第2页、为i时表示第(i+1)页。
使用templates中的方法进行查询
@Test
public void testNativeSearchQuery(){
// 创建一个查询对象
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.queryStringQuery("小说").defaultField("content"))
.withPageable(PageRequest.of(1,5))
.build();
// 执行查询
SearchHits<Article> search = template.search(query, Article.class);
List<SearchHit<Article>> searchHits = search.getSearchHits();
for (SearchHit<Article> searchHit : searchHits) {
System.out.println(searchHit.getContent());
}
}
修改索引中的文档
相当于操作数据库 update t_article set auth=‘塞林格’ where id = 14;
@Test
public void updateArticleDoc(){
Map<String,Object> updateMap = new HashMap<>();
updateMap.put("id",14);
updateMap.put("auth","塞林格");
// 修改数据库
//articleDao.updateArticle(updateMap);
IndexRequest indexRequest = new IndexRequest();
indexRequest.source(updateMap);
Document document = Document.from(updateMap);
UpdateQuery updateQuery = UpdateQuery.builder(updateMap.get("id").toString())
.withDocAsUpsert(true)
.withDocument(document)
.build();
template.update(updateQuery, IndexCoordinates.of("article_index"));
}
在es的其他版本中,使用UpdateQueryBuilder()方法修改文档。但是我使用的7.6.2版本中没有这个方法。
UpdateQuery updateQuery = new UpdateQueryBuilder()
.withClass(Article.class)
.withId("14")
.withIndexRequest(indexRequest)
.build();
template.update(updateQuery);