目标:
- 能够使用java客户端完成创建、删除索引的操作
- 能够使用java客户端完成文档的增删改的操作
- 能够使用java客户端完成文档的查询操作
- 能够完成文档的分页操作
- 能够完成文档的高亮查询操作
- 能够搭建Spring Data ElasticSearch的环境
- 能够完成Spring Data ElasticSearch的基本增删改查操作
- 能够掌握基本条件查询的方法命名规则
文章目录
一、使用Java客户端管理ES
1、创建索引库(相当于创建了一个数据库)
步骤:
1)创建一个Java工程
新建一个空的java工程,在工程下新增一个maven的module,注意jdk的选择,必须是9或者9以上的版本才行!
2)添加jar包,添加maven的坐标
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.xxx</groupId>
<artifactId>ES-first</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
3)编写测试方法实现创建索引库
1、创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。
2、创建一个客户端Client对象
3、使用client对象创建一个索引库
4、关闭client对象
在进行这些操作之前,需要先把elasticSearch服务器开启,这里使用了一个集群服务器,三个节点构成的。再启动head打开可视化页面。
public class ElasticSearchClient {
@Test
public void createIndex() throws Exception{
//1、创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。
Settings settings = Settings.builder()
.put("cluster.name","my-elasticsearch2")
.build();
//2、创建一个客户端Client对象
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
//3、使用client对象创建一个索引库
client.admin().indices().prepareCreate("index_hello2")
//执行操作
.get();
//4、关闭client对象
client.close();
}
}
2、使用Java客户端设置Mappings(相当于创建表的时候设计表的结构)
设计表的结构,定义好表中不同的数据的类型(int varchar…)。
相当于创建
步骤:
1)创建一个Settings对象
2)创建一个Client对象
3)创建一个mapping信息,应该是一个json数据,可以是字符串,也可以是XContextBuilder对象
4)使用client向es服务器发送mapping信息
5)关闭client对象
public void setMapping() throws Exception{
//1、创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。
Settings settings = Settings.builder()
.put("cluster.name","my-elasticsearch2")
.build();
//2、创建一个客户端Client对象
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303));
//创建一个Mappings信息
/*{
"article":{
"properties":{
"id":{
"type":"long",
"store":true
},
"title":{
"type":"text",
"store":true,
"index":true,
"analyzer":"ik_smart"
},
"content":{
"type":"text",
"store":true,
"index":true,
"analyzer":"ik_smart"
}
}
}
}*/
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject("article")
.startObject("properties")
.startObject("id")
.field("type","long")
.field("store", true)
.endObject()
.startObject("title")
.field("type", "text")
.field("store", true)
.field("analyzer", "ik_smart")
.endObject()
.startObject("content")
.field("type", "text")
.field("store", true)
.field("analyzer","ik_smart")
.endObject()
.endObject()
.endObject()
.endObject();
//使用client把mapping信息设置到索引库中
client.admin().indices()
//设置要做映射的索引
.preparePutMapping("index_hello2")
//设置要做映射的type
.setType("article")
//mapping信息,可以是XContentBuilder对象可以是json格式的字符串
.setSource(builder)
//执行操作
.get();
//关闭链接
client.close();
}
3、添加文档(相当于向表中添加一行数据)
步骤:
1)创建一个Settings对象
2)创建一个Client对象
3)创建一个文档对象,创建一个json格式的字符串,或者使用XContentBuilder
4)使用Client对象吧文档添加到索引库中
5)关闭client
public void addDocument() throws Exception{
//1)创建一个Settings对象
//2)创建一个Client对象
//3)创建一个文档对象,创建一个json格式的字符串,或者使用XContentBuilder
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.field("id",1l)
.field("title","mapping信息,可以是XContentBuilder对象可以是json格式的字符串")
.field("content","设置要做映射的索引")
.endObject();
//4)使用Client对象把文档添加到索引库中
client.prepareIndex()
.setIndex("index_hello2")
.setType("article")
.setId("1")
.setSource(builder)
//执行操作
.get();
//5)关闭client
client.close();
}
4、添加文档第二种方式
创建一个pojo类(其实就是JavaBean那样的东西)
使用工具类把pojo转换成json字符串
把文档写入索引库
public void addDocument2() throws Exception{
//1)创建一个Settings对象
//2)创建一个Client对象
//3)创建一个pojo类(其实就是JavaBean那样的东西)
Article article = new Article();
article.setId(3l);
article.setTitle("新增加的标题3");
article.setContent("新增加的内容3");
//4)使用工具类把pojo转换成json字符串
ObjectMapper objectMapper = new ObjectMapper();
String articleValue = objectMapper.writeValueAsString(article);
System.out.println(articleValue);
//5)把文档写入索引库
client.prepareIndex("index_hello2","article","3")
.setSource(articleValue, XContentType.JSON)
.get();
//关闭client对象
client.close();
}
二、使用es客户端实现搜索
查询步骤:
1)创建一个Client对象
2)创建一个查询对象,可以使用QueryBuilders工具类创建QueryBuilder对象。
3)使用client执行查询
4)得到查询的结果。
5)取查询结果的总记录数
6)取查询结果列表
7)关闭client
1、根据id搜索
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "2");
public void search() throws Exception{
//创建一个client对象
//创建一个查询对象
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1","2");
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//取出查询的结果
SearchHits hits = searchResponse.getHits();
//取出查询的总记录数
System.out.println(hits.getTotalHits());
//取出详细内容
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
//以json的格式打印所有的信息
System.out.println(searchHit.getSourceAsString());
System.out.println("-----------------文档属性");
Map<String,Object> map = searchHit.getSource();
System.out.println(map.get("id"));
System.out.println(map.get("title"));
System.out.println(map.get("content"));
}
}
2、根据Term查询(关键词)
QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "北方");
public void searchByTerm() throws Exception{
//创建一个client对象
//创建一个查询对象
QueryBuilder queryBuilder = QueryBuilders.termQuery("title","标题");
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//取出查询的结果
SearchHits hits = searchResponse.getHits();
//取出查询的总记录数
System.out.println(hits.getTotalHits());
//取出详细内容
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
//以json的格式打印所有的信息
System.out.println(searchHit.getSourceAsString());
System.out.println("-----------------文档属性");
Map<String,Object> map = searchHit.getSource();
System.out.println(map.get("id"));
System.out.println(map.get("title"));
System.out.println(map.get("content"));
}
}
3、QueryString查询方式(带分析的查询)
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("速度与激情") .defaultField("title");
public void searchByQeryString() throws Exception{
//创建一个client对象
//创建一个查询对象
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("标题与mapping")
.defaultField("title");
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello2")
.setTypes("article")
.setQuery(queryBuilder)
.get();
//取出查询的结果
SearchHits hits = searchResponse.getHits();
//取出查询的总记录数
System.out.println(hits.getTotalHits());
//取出详细内容
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
//以json的格式打印所有的信息
System.out.println(searchHit.getSourceAsString());
System.out.println("-----------------文档属性");
Map<String,Object> map = searchHit.getSource();
System.out.println(map.get("id"));
System.out.println(map.get("title"));
System.out.println(map.get("content"));
}
}
4、分页的处理
在client对象执行查询之前,设置分页信息。
然后再执行查询
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello")
.setTypes("article")
.setQuery(queryBuilder)
//设置分页信息
.setFrom(0)
//每页显示的行数
.setSize(5)
.get();
分页需要设置两个值,一个from、size
from:起始的行号,从0开始。
size:每页显示的记录数
public void searchByPages() throws Exception{
//创建一个client对象
//创建一个查询对象
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("配置")
.defaultField("title");
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello2")
.setTypes("article")
.setQuery(queryBuilder)
//设置起始分页的页数
.setFrom(0)
//设置每页的最大查询数量
.setSize(5)
.get();
//取出查询的结果
SearchHits hits = searchResponse.getHits();
//取出查询的总记录数
System.out.println(hits.getTotalHits());
//取出详细内容
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()){
SearchHit searchHit = iterator.next();
//以json的格式打印所有的信息
System.out.println(searchHit.getSourceAsString());
System.out.println("-----------------文档属性");
Map<String,Object> map = searchHit.getSource();
System.out.println(map.get("id"));
System.out.println(map.get("title"));
System.out.println(map.get("content"));
}
}
5、查询结果高亮显示
(1)高亮的配置
1)设置高亮显示的字段
2)设置高亮显示的前缀
3)设置高亮显示的后缀
(2)在client对象执行查询之前,设置高亮显示的信息。
(3)遍历结果列表时可以从结果中取高亮结果。
//带高亮显示的搜索方法
private void search(QueryBuilder queryBuilder, String highlightField) throws Exception {
HighlightBuilder highlightBuilder = new HighlightBuilder();
//高亮显示的字段
highlightBuilder.field(highlightField);
highlightBuilder.preTags("<em>");
highlightBuilder.postTags("</em>");
//执行查询
SearchResponse searchResponse = client.prepareSearch("index_hello2")
.setTypes("article")
.setQuery(queryBuilder)
//设置分页信息
.setFrom(0)
//每页显示的行数
.setSize(5)
//设置高亮信息
.highlighter(highlightBuilder)
.get();
//取查询结果
SearchHits searchHits = searchResponse.getHits();
//取查询结果的总记录数
System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
Iterator<SearchHit> iterator = searchHits.iterator();
while(iterator.hasNext()) {
SearchHit searchHit = iterator.next();
//打印文档对象,以json格式输出
System.out.println(searchHit.getSourceAsString());
//取文档的属性
System.out.println("-----------文档的属性");
Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
System.out.println(document.get("title"));
System.out.println(document.get("content"));
System.out.println("************高亮结果");
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
System.out.println(highlightFields);
//取title高亮显示的结果
HighlightField field = highlightFields.get(highlightField);
Text[] fragments = field.getFragments();
if (fragments != null) {
String title = fragments[0].toString();
System.out.println(title);
}
}
//关闭client
client.close();
}
三、SpringDataElasticSearch
1、工程搭建
1)创建一个java工程(maven工程)。
2)把相关jar包添加到工程中。如果maven工程就添加坐标。
<?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.xxx</groupId>
<artifactId>springData-ElasticSearch</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.9</maven.compiler.source>
<maven.compiler.target>1.9</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.0.5.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
</dependencies>
</project>
3)创建一个spring的配置文件
1、配置elasticsearch:transport-client
2、elasticsearch:repositories:包扫描器,扫描dao
3、配置elasticsearchTemplate对象,就是一个bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/elasticsearch
http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd
">
<!-- elasticSearch客户端对象配置 -->
<elasticsearch:transport-client id="esClient" cluster-name="my-elasticsearch2"
cluster-nodes="127.0.0.1:9301;127.0.0.1:9302;127.0.0.1:9303;"/>
<!-- 配置包扫描器,扫描到的接口 -->
<elasticsearch:repositories base-package="com.xxx.es.repositories"/>
<!-- 配置es的模板-->
<bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="esClient"></constructor-arg>
</bean>
</beans>
2、管理索引库
1、创建一个Entity类,其实就是一个JavaBean(pojo)映射到一个Document上
package com.xxx.es.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import java.io.Serializable;
@Document(indexName = "new_blog",type = "article")
public class Article implements Serializable {
@Id
@Field(type = FieldType.Long,store = true)
private Long id;
@Field(type = FieldType.text,store = true,analyzer = "ik_smart")
private String title;
@Field(type = FieldType.text,store = true,analyzer = "ik_smart")
private String content;
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 getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
需要添加一些注解进行标注。
2、创建一个Dao,是一个接口,需要继承ElasticSearchRepository接口。
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
List<Article> findByTitle(String title);
List<Article> findByTitleOrContent(String title,String content);
}
3、编写测试代码。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private ElasticsearchTemplate template;
@Test
public void createIndex() throws Exception{
//创建索引,并配置映射关系
template.createIndex(Article.class);
}
3、创建索引
直接使用ElasticsearchTemplate对象的createIndex方法创建索引,并配置映射关系。
4、添加、更新文档
1)创建一个Article对象
2)使用ArticleRepository对象向索引库中添加文档。
5、删除文档
直接使用ArticleRepository对象的deleteById方法直接删除。
6、查询索引库
直接使用ArticleRepository对象的查询方法。
7、自定义查询方法
需要根据SpringDataES的命名规则来命名。
如果不设置分页信息,默认带分页,每页显示10条数据。
如果设置分页信息,应该在方法中添加一个参数Pageable
Pageable pageable = PageRequest.of(0, 15);
注意:设置分页信息,默认是从0页开始。
可以对搜索的内容先分词然后再进行查询。每个词之间都是and的关系。
8、使用原生的查询条件查询
NativeSearchQuery对象。
使用方法:
1)创建一个NativeSearchQuery对象
设置查询条件,QueryBuilder对象
2)使用ElasticSearchTemplate对象执行查询
3)取查询结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataElasticSearchTest {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private ElasticsearchTemplate template;
@Test
public void createIndex() throws Exception{
//创建索引,并配置映射关系
template.createIndex(Article.class);
}
@Test
public void addDocument(){
//创建一个Article对象
Article article = new Article();
article.setId(Long.parseLong(3+""));
article.setTitle("这是一个系统3");
article.setContent("系统内部的设置33");
articleRepository.save(article);
}
@Test
public void addDocument2(){
for (int i = 1; i < 30; i++) {
//创建一个Article对象
Article article = new Article();
article.setId(Long.parseLong(i+""));
article.setTitle("这是一个系统"+i);
article.setContent("系统内部的设置"+i);
articleRepository.save(article);
}
}
@Test
public void deleteDocument(){
//根据id删除文档
// articleRepository.deleteById(1l);
//删除全部的文档
articleRepository.deleteAll();
//修改文档(底层原理也是先删除后添加)
}
@Test
public void findAll() throws Exception{
Iterable<Article> articles = articleRepository.findAll();
//jdk1.8后支持的新打印方法
articles.forEach(a-> System.out.println(a));
}
@Test
public void findById() throws Exception{
Optional<Article> optional = articleRepository.findById(1l);
Article article = optional.get();
System.out.println(article);
}
@Test
public void findByTitle(){
List<Article> articles = articleRepository.findByTitle("系统");
articles.stream().forEach(a->System.out.println(a));
}
@Test
public void testFindByTitleOrContent(){
articleRepository.findByTitleOrContent("系统","系统")
.forEach(a->System.out.println(a));
// Pageable pageable = PageRequest.of(1, 15);
// articleRepository.findByTitleOrContent("maven", "系统1", pageable)
// .forEach(a-> System.out.println(a));
}
@Test
public void testNativeSearchQuery() throws Exception {
//创建一个查询对象,使用上边的查询的时候,当输入的是一句话,会先分词,然后and词语进行查询的,这回导致很多想要的结果查询不到。
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.queryStringQuery("系统是一个工具").defaultField("title"))
.withPageable(PageRequest.of(0, 15))
.build();
//执行查询
List<Article> articleList = template.queryForList(query, Article.class);
articleList.forEach(a-> System.out.println(a));
}
}