SpringBoot高级-检索-SpringBoot整合Jest操作ES

接下来就用SpringBoot来整合ElasticSearch进行测试,pom文件引入了spring-boot-starter-data-elasticsearch,

其实加了data都是用springdata来操作的,他这里确实引入了

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
	<version>1.5.12.RELEASE</version>
</dependency>

SpringBoot默认使用SpringData操作ElasticSearch模块进行操作的,那我们再来分析一下ES的自动配置,来到autoconfigure里边
<?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.learn</groupId>
	<artifactId>springboot-03-elastic</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>springboot-03-elastic</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.12.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>
		<!--SpringBoot默认使用SpringData ElasticSearch模块进行操作-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
		<dependency>
			<groupId>io.searchbox</groupId>
			<artifactId>jest</artifactId>
			<version>5.3.3</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>
这里有一个data,org.springframework.boot.autoconfigure.data,

data里面有elasticsearch,这是SpringData对ElasticSearch的支持,包括下边大家来看

org.springframework.boot.autoconfigure.data.elasticsearch

下边还有一个elasticsearch

org.springframework.boot.autoconfigure.elasticsearch.jest

这叫jest,这是一个非常流行的ES客户端工具,他利用HTTP的方式,跟ES进行交互的,所以它有两种方式来操作ES,

我们来记录一下,SpringBoot默认支持两种技术,来和ES交互,第一种是JEST,第二种是SpringData ElasticSearch,

那我们来看哪种技术生效,到底怎么生效呢,我们还是来下翻,我们先看jest的自动配置,来看JestAutoConfiguration,

@Configuration
@ConditionalOnClass(JestClient.class)
@EnableConfigurationProperties(JestProperties.class)
@AutoConfigureAfter(GsonAutoConfiguration.class)
public class JestAutoConfiguration {

由于我们缺少导了一个包,其实是不生效的,所以默认如果想要他生效,我们需要导入这个包

import io.searchbox.client.JestClient;

JEST默认是不生效的,需要导入jest的工具包,这里有一个完整描述,我们来看SpringData的自动配置,如果生效就用9200端口

进行HTTP交互

@Bean(destroyMethod = "shutdownClient")
@ConditionalOnMissingBean
public JestClient jestClient() {
	JestClientFactory factory = new JestClientFactory();
	factory.setHttpClientConfig(createHttpClientConfig());
	return factory.getObject();
}

SpringData有ElasticsearchAutoConfiguration,他给我们配置了什么呢,他给我们配置了一个连接,

@Bean
@ConditionalOnMissingBean
public Client elasticsearchClient() {
	try {
		return createClient();
	}
	catch (Exception ex) {
		throw new IllegalStateException(ex);
	}
}

这个客户端需要指定一些属性,比如集群里面每一个节点的信息,

private Client createNodeClient() throws Exception {
	Settings.Builder settings = Settings.settingsBuilder();
	for (Map.Entry<String, String> entry : DEFAULTS.entrySet()) {
		if (!this.properties.getProperties().containsKey(entry.getKey())) {
			settings.put(entry.getKey(), entry.getValue());
		}
	}
	settings.put(this.properties.getProperties());
	Node node = new NodeBuilder().settings(settings)
			.clusterName(this.properties.getClusterName()).node();
	this.releasable = node;
	return node.client();
}

帮我们配置了这么些内容,第一个给我们一个客户端,我们可以用客户端,

public String getClusterNodes() {
	return this.clusterNodes;
}

我们需要配这个信息,

public String getClusterName() {
	return this.clusterName;
}

这是我们节点的信息,第二个他还为我们配了什么呢,这个我们就不看了,ElasticsearchDataAutoConfiguration,

他给我们配了一个ElasticsearchTemplate

@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Client.class)
public ElasticsearchTemplate elasticsearchTemplate(Client client,
		ElasticsearchConverter converter) {
	try {
		return new ElasticsearchTemplate(client, converter);
	}
	catch (Exception ex) {
		throw new IllegalStateException(ex);
	}
}

我们这个写template用的已经非常多了,比如我们以前用的JDBC template,操作Redis的Template,操作Rabbit的

Template,那么由此可见,Spring在整合很多技术的时候呢,都会引入相关的Template操作就行了,他来操作ES,

还引入了ElasticsearchRepositoriesAutoConfiguration,他的作用就是启用了ElasticsearchRepository接口,

他就类似于JPA的操作方式一样,我们可以写一个接口,来继承于这个Repository,

@NoRepositoryBean
public interface ElasticsearchRepository<T, ID extends Serializable> extends ElasticsearchCrudRepository<T, ID> {

	<S extends T> S index(S entity);

	Iterable<T> search(QueryBuilder query);

	Page<T> search(QueryBuilder query, Pageable pageable);

	Page<T> search(SearchQuery searchQuery);

	Page<T> searchSimilar(T entity, String[] fields, Pageable pageable);

	void refresh();

	Class<T> getEntityClass();
}

ES的增删改查操作,我们的接口就会有相关的方法,比如这个方法有索引,我们ES中存数据,还有搜索等等,我们可以用这种编程方式,

我们可以编写ElasticsearchRepository这个的子接口,来操作ES,这就是类似JPA的操作方式一样,这两种技术,我们先来测Jest,

SpringData我们稍后来测,我先把SpringData先注掉,springdata来操作的我们先注掉,

<!--SpringBoot默认使用SpringData ElasticSearch模块进行操作-->
<!-- <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency> -->

我们来导入jest

<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
<dependency>
	<groupId>io.searchbox</groupId>
	<artifactId>jest</artifactId>
	<version>5.3.3</version>
</dependency>

我们先来看JestAutoConfiguration,

protected HttpClientConfig createHttpClientConfig() {
	HttpClientConfig.Builder builder = new HttpClientConfig.Builder(
			this.properties.getUris());
	if (StringUtils.hasText(this.properties.getUsername())) {
		builder.defaultCredentials(this.properties.getUsername(),
				this.properties.getPassword());
	}
	String proxyHost = this.properties.getProxy().getHost();
	if (StringUtils.hasText(proxyHost)) {
		Integer proxyPort = this.properties.getProxy().getPort();
		Assert.notNull(proxyPort, "Proxy port must not be null");
		builder.proxy(new HttpHost(proxyHost, proxyPort));
	}
	Gson gson = this.gsonProvider.getIfUnique();
	if (gson != null) {
		builder.gson(gson);
	}
	builder.multiThreaded(this.properties.isMultiThreaded());
	builder.connTimeout(this.properties.getConnectionTimeout())
			.readTimeout(this.properties.getReadTimeout());
	customize(builder);
	return builder.build();
}
比如用户名,密码,重要的是uris,

@ConfigurationProperties(prefix = "spring.elasticsearch.jest")
public class JestProperties {

	/**
	 * Comma-separated list of the Elasticsearch instances to use.
	 */
	private List<String> uris = new ArrayList<String>(
			Collections.singletonList("http://localhost:9200"));

我们是远程主机的,我们只需要配置

spring.elasticsearch.jest.uris=http://59.110.158.145:9200

我们先来看有没有启动报错,打印连接池已经连接到9200端口了
我们给ES中保存索引,也就是保存工作,一个文档,我们写一个bean类,叫Article,我们要索引一篇文章,

这个文章有文章的id,来写一个Integer,还有作者,还有文章的标题,还有文章的内容,我们还要给id字段

加一个id注解,来标识这是一个主键
package com.learn.bean;

import io.searchbox.annotations.JestId;

public class Article {

	@JestId
	private Integer id;
	
	private String author;
	
	private String title;
	
	private String content;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	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 + ", author=" + author + ", title=" + title + ", content=" + content + "]";
	}
	
}
如何将Article保存在ES中呢,比如我们new了一个Article,我们把它创建出来,我们来设置上他的属性,

这是我们的一个文章,如何给ES中保存呢,非常简单,我们Jest里面有一个对象,new一个Index,里面的buider,

我们要指定一个索引位置,比如我们把他保存在china,类型是什么呢,我们也来继续指定,type来指定类型,比如

news都是一些新闻,保存完我们还可以指定一个id,这个id是什么呢,我们把这几个写好了以后呢,我们接下来点一个

build构建,这是我们一个index索引,构建一个索引功能,然后就来执行,指定的时候可能会抛异常,同样的位置try 

catch一下,这是我们接下来执行,那我们来测试一下能不能run,我们发现执行成功,控制台也没有报错,我们来查询

一下,我们有一个索引叫china,我们找news/1

59.110.158.145:9200/china/news/1
package com.learn.springboot;

import java.io.IOException;

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.test.context.junit4.SpringRunner;

import com.learn.bean.Article;

import io.searchbox.client.JestClient;
import io.searchbox.core.Index;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootAmqpApplicationTests {
	
	@Autowired
	JestClient jestClient;
	
	@Test
	public void contextLoads() {
		// 1.给ES中索引(保存)一个文档
		Article article = new Article();
		article.setId(1);
		article.setTitle("好消息");
		article.setAuthor("zhangshan");
		article.setContent("Hello World");
		
		// 构建一个索引功能
		Index index = new Index.Builder(article).index("china").type("news").build();
		
		try {
			// 执行
			jestClient.execute(index);
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}
}

我们发现查到了1号的新闻,我们再来尝试一下搜索,使用Jest来进行搜索,我们就以全文搜索为例,

这个搜索我们怎么做呢,还是一样,我们这个搜索还是非常简单,Build里面就是查询表达式,我们把

JSON直接复制来,指定在哪个索引下搜索,我们在china这个索引下,我们在哪个类型下搜,我们来添加

一个news,我们都在这儿搜,然后选一个build,搜索操作我们来构建出来,那么构建出来以后呢,还是一样,

用JestClient来执行就行了,把这个搜索放进来,执行完以后会返回一个SearchResult,拿到result给大家输出一下,

这里列出了非常多的方法,比如获得命中的记录,转成需要的类型,而且还可以获取相关性的最高得分,总记录数,

把它的字符串打印一下就行了

{"took":5,
"timed_out":false,
"_shards":{"total":5,"successful":5,"failed":0},
"hits":{"total":1,"max_score":0.19178301,
"hits":[{"_index":"china","_type":"news",
"_id":"1","_score":0.19178301,
"_source":{"id":1,"author":"zhangshan","title":"好消息","content":"Hello World"}}]}}
package com.learn.springboot;

import java.io.IOException;

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.test.context.junit4.SpringRunner;

import com.learn.bean.Article;

import io.searchbox.client.JestClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.Search.Builder;
import io.searchbox.core.SearchResult;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootAmqpApplicationTests {
	
	@Autowired
	JestClient jestClient;
	
	@Test
	public void contextLoads() {
		// 1.给ES中索引(保存)一个文档
		Article article = new Article();
		article.setId(1);
		article.setTitle("好消息");
		article.setAuthor("zhangshan");
		article.setContent("Hello World");
		
		// 构建一个索引功能
		Index index = new Index.Builder(article).index("china").type("news").build();
		
		try {
			// 执行
			jestClient.execute(index);
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}
	
	@Test
	public void search() {
		
		// 查询表达式
		String json = "{\r\n" + 
				"    \"query\": {\r\n" + 
				"        \"match\": {\r\n" + 
				"            \"content\": \"hello\"\r\n" + 
				"        }\r\n" + 
				"    }\r\n" + 
				"}";
		
		// 构建搜索功能
		Search search = new Search.Builder(json).addIndex("china").addType("news").build();
		
		try {
			SearchResult result = jestClient.execute(search);
			System.out.println(result.getJsonString());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值