Elasticsearchjava客户端有两种选择
1、使用springData封装,但是跟新跟不上官方版本,我这里使用的ElasticSearch是7.6.0,SpringDataElasticSearch现在还不能支持7.6.0
2、使用官方推荐的elasticsearch-rest-high-level-client,该组件是由官方提供,提供有最新版本的
本次研究使用SpringBoot结合“elasticsearch-rest-high-level-client”,导入Maven依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.1</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.6.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.6.1</version>
</dependency>
配置application.yml,如果ElasticSearch没开启安全认证就无须设置username和password
elasticsearch:
address: 192.168.5.166:9200
username: elastic
password: 123456
创建ESConfig类,
package cn.rsthe.es.config;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ESConfig {
private static final int ADDRESS_LENGTH = 2;
private static final String HTTP_SCHEME = "http";
/** 权限验证 */
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
/** 使用冒号隔开ip和端口 */
@Value("${elasticsearch.address}")
private String address;
@Value("${elasticsearch.username}")
private String username;
@Value("${elasticsearch.password}")
private String password;
@Bean
public RestClientBuilder restClientBuilder() {
HttpHost hosts = makeHttpHost(address);
log.debug("hosts:{}", hosts);
//配置权限验证
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestClientBuilder restClientBuilder = RestClient.builder(hosts).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
return restClientBuilder;
}
@Bean(name = "highLevelClient",destroyMethod = "close")
public RestHighLevelClient highLevelClient(@Autowired RestClientBuilder restClientBuilder) {
return new RestHighLevelClient(restClientBuilder);
}
/**
* 处理请求地址
* @param s
* @return HttpHost
*/
private HttpHost makeHttpHost(String s) {
String[] address = s.split(":");
if (address.length == ADDRESS_LENGTH) {
String ip = address[0];
int port = Integer.parseInt(address[1]);
return new HttpHost(ip, port, HTTP_SCHEME);
} else {
return null;
}
}
}
1、创建索引,创建索引的方式有三种
- 以类似Map的形式创建
@Test
public void testAdd(){
// 设置创建的索引名称
CreateIndexRequest request = new CreateIndexRequest("testindex");
//封装属性 类似于json格式
Map<String, Object> jsonMap = new HashMap<>();
Map<String, Object> properties = new HashMap<>();
Map<String, Object> content = new HashMap<>();
content.put("type", "integer");
Map<String, Object>account = new HashMap<>();
content .put("type", "text");
content .put("analyzer", "ik_max_word");
properties.put("id", content);
properties.put("account", account);
jsonMap.put("properties", properties);
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 2)
);
try {
CreateIndexResponse createIndexResponse = highLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.err.println(createIndexResponse);
} catch (IOException e) {
e.printStackTrace();
}
}
- 第二种使用Builder的方式
@Test
public void testAdd() throws Exception{
// 设置创建的索引名称
CreateIndexRequest request = new CreateIndexRequest("testindex1-1");
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.startObject("properties");
{
builder.startObject("message");
{
builder.field("type", "text");
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
request.mapping(builder);
try {
CreateIndexResponse createIndexResponse = highLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.err.println(createIndexResponse);
} catch (IOException e) {
e.printStackTrace();
}
}
- 第三种以json的方式
@Test
public void testAdd() throws Exception{
// 设置创建的索引名称
CreateIndexRequest request = new CreateIndexRequest("testindex2");
request.mapping(
"{\n" +
" \"properties\": {\n" +
" \"message\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
"}",
XContentType.JSON);
try {
CreateIndexResponse createIndexResponse = highLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.err.println(createIndexResponse);
} catch (IOException e) {
e.printStackTrace();
}
}
数据操作
需要注意的是,从ElasticSearch5.x开始就提出了弱化索引类型_type的使用,期初,我们说“索引”和关系型数据库的“库”是相似的,“类型”和“表”示对等的。这是一个不正确的对比,导致了不正确的假设。在关系型数据库中,“表”是相互独立的,一个“表”里面列和另一个“表”里的同名列是没有关系的,互不影响的。但是在类型里字段不是这样的,比如:两个不同type下的两个user_name,在ES同一个索引下,其实它们会被认为是同一个filed,你必须在两个不同的type中定义相同的 filed映射,否则,不同type中的相同字段名称就会在处理中国出现冲突,导致Lucene处理效率的下降。所有在ElasticSearch7.x就完全出去type,每个索引都默认只有_doc.
- 新增数据,可以直接使用Vo类进行数据设置
@Test
public void testPut() throws Exception{
Goods goods = new Goods();
goods.setGid(23L);
goods.setDelflag(1);
goods.setLastin(new Date());
goods.setName("Hello");
goods.setNote("你好");
goods.setPhoto("nothing");
goods.setPrice(19999.9);
goods.setRecorder("nothing");
goods.setStid(1L);
goods.setStornum(1);
goods.setWeight(15.0);
goods.setWid(1L);
goods.setWiid(1L);
IndexRequest request = new IndexRequest("drp");
request.id(goods.getGid().toString());
request.source(JSON.toJSONString(goods),XContentType.JSON);
highLevelClient.index(request,RequestOptions.DEFAULT);
}
- 查询数据
@Test
public void testGet() throws Exception{
GetRequest request = new GetRequest("drp","23");
GetResponse documentFields = highLevelClient.get(request, RequestOptions.DEFAULT);
if (documentFields.isExists()){
String sourceAsString = documentFields.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
System.err.println(goods);
}
}
- 更新数据
@Test
public void testUpdate() throws Exception{
Goods goods = new Goods();
goods.setGid(23L);
goods.setDelflag(1);
goods.setLastin(new Date());
goods.setName("Hello");
goods.setNote("你好ya ,周末");
goods.setPhoto("nothing");
goods.setPrice(19999.9);
goods.setRecorder("nothing");
goods.setStid(1L);
goods.setStornum(1);
goods.setWeight(15.0);
goods.setWid(1L);
goods.setWiid(1L);
UpdateRequest request = new UpdateRequest("drp",goods.getGid().toString());
request.doc(JSON.toJSONString(goods),XContentType.JSON);
UpdateResponse update = highLevelClient.update(request, RequestOptions.DEFAULT);
System.err.println(update);
}
- 删除数据
@Test
public void testDelete() throws IOException {
DeleteRequest request = new DeleteRequest("drp","23");
DeleteResponse delete = highLevelClient.delete(request, RequestOptions.DEFAULT);
System.err.println(delete.status());
}
- 基本分页查询
@SneakyThrows
@Test
public void listPage() {
int pagesize = 1; // 页数
int linesize = 20; // 每页显示条数
String content = "三地方大";// 模糊查询
// 创建索引请求,可以传入操作索引,也可以后面在设置
SearchRequest request = new SearchRequest("drp");
// 创建索引构建者
SearchSourceBuilder builder = new SearchSourceBuilder();
// 构建搜索属性
builder.from((pagesize - 1) * linesize); // 从第几开始
builder.size(linesize); //返回条数
builder.sort(new FieldSortBuilder("price").order(SortOrder.ASC)); //对字段宁进行排序
if (!StringUtils.isEmpty(content)){
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 完全匹配字段内容,“name”:字段,后面的参数是匹配内容
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("wiid","5");
// 完全匹配字段内容,“name”:字段,后面的参数是匹配内容,可以设置匹配多个
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("note","三地","耐");
//单个匹配, field不支持通配符, 前缀具高级特性
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note",content).fuzziness(Fuzziness.AUTO);
// 匹配全部
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
boolQueryBuilder.must(matchAllQueryBuilder);
builder.query(boolQueryBuilder);
}
// 传入构建进行搜索
request.source(builder);
SearchResponse search = highLevelClient.search(request, RequestOptions.DEFAULT);
// 处理结果
System.err.println(search.status());
List<Goods> list = new ArrayList<>();
// 获取返回数据
SearchHits hits = search.getHits();
hits.forEach(item -> list.add(JSON.parseObject(item.getSourceAsString(),Goods.class)));
System.err.println(list);
}