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">
<parent>
<artifactId>xc-framework-parent</artifactId>
<groupId>com.xuecheng</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../xc-framework-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>xc-service-search</artifactId>
<dependencies>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-framework-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-framework-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.9</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: ${port:40100}
spring:
application:
name: xc-search-service
xuecheng:
elasticsearch:
hostlist: ${eshostlist:127.0.0.1:9200} #多个结点中间用逗号分隔
logback-spring.xml
<configuration>
<property name="LOG_HOME" value="/Users/xiaoge/Downloads/CMSPROJECT/logs"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
<charset>utf8charset>
encoder>
appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/xc.%d{yyyy-MM-dd}.logfileNamePattern>
rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
encoder>
appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0discardingThreshold>
<queueSize>512queueSize>
<appender-ref ref="FILE"/>
appender>
<logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE"/>
logger>
<logger name="org.springframework.boot" level="DEBUG"/>
<root level="info">
<appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/>
root>
configuration>
ElasticsearchConfig
package com.xuecheng.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Administrator
* @version 1.0
**/
@Configuration
public class ElasticsearchConfig {
@Value("${xuecheng.elasticsearch.hostlist}")
private String hostlist;
@Bean
public RestHighLevelClient restHighLevelClient(){
//解析hostlist配置信息
String[] split = hostlist.split(",");
//创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
//创建RestHighLevelClient客户端
return new RestHighLevelClient(RestClient.builder(httpHostArray));
}
//项目主要使用RestHighLevelClient,对于低级的客户端暂时不用
@Bean
public RestClient restClient(){
//解析hostlist配置信息
String[] split = hostlist.split(",");
//创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
return RestClient.builder(httpHostArray).build();
}
}
SearchApplication
package com.xuecheng.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
/**
* @author Administrator
* @version 1.0
**/
@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.search")//扫描实体类
@ComponentScan(basePackages={"com.xuecheng.api"})//扫描接口
@ComponentScan(basePackages={"com.xuecheng.search"})//扫描本项目下的所有类
@ComponentScan(basePackages={"com.xuecheng.framework"})//扫描common下的所有类
public class SearchApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SearchApplication.class, args);
}
}
TestElasticSearch
package com.xuecheng.search;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
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 java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: 潇哥
* @DateTime: 2020/12/3 下午6:08
* @Description: 测试ElasticSearch
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestElasticSearch {
@Autowired
private RestHighLevelClient restHighLevelClient;
@Autowired
private RestClient restClient;
@Test
public void testCreateIndex() throws IOException {
// 创建索引请求对象
CreateIndexRequest createIndexRequest = new CreateIndexRequest("xc_course");
// 设置分片, 副本
createIndexRequest.settings(Settings.builder().put("number_of_shards","1").put("number_of_replicas","0"));
// 创建映射
createIndexRequest.mapping("doc","{\"properties\": {\"name\": {\"type\": \"keyword\"},\"description\": {\"type\": \"text\",\"analyzer\":\"ik_max_word\",\"search_analyzer\":\"ik_smart\"}, \"pic\":{\"type\":\"text\",\"index\":false},\"studymodel\":{\"type\":\"keyword\"} }}",XContentType.JSON);
// 操作索引的客户端
IndicesClient indicesClient = restHighLevelClient.indices();
// 创建索引及映射关系
CreateIndexResponse createIndexResponse = indicesClient.create(createIndexRequest);
// 得到响应结果
boolean acknowledged = createIndexResponse.isAcknowledged();
System.out.println(acknowledged);
}
/**
* 删除索引
* @throws IOException
*/
@Test
public void testDeleteIndex() throws IOException {
// 删除索引请求对象
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xc_course");
// 操作索引的客户端
IndicesClient indicesClient = restHighLevelClient.indices();
// 删除索引
AcknowledgedResponse acknowledgedResponse = indicesClient.delete(deleteIndexRequest);
// 得到响应
boolean acknowledged = acknowledgedResponse.isAcknowledged();
System.out.println(acknowledged);
}
/**
* 添加文档
*/
@Test
public void testAddDoc() throws IOException {
//准备json数据
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("name", "spring cloud实战");
jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战Spring Boot 4.注册中心eureka。");
jsonMap.put("studymodel", "201001");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");
jsonMap.put("timestamp", dateFormat.format(new Date()));
jsonMap.put("price", 5.6f);
//索引请求对象
IndexRequest indexRequest = new IndexRequest("xc_course", "doc"); //指定索引文档内容
// 添加数据
indexRequest.source(jsonMap);
//索引响应对象
IndexResponse indexResponse = restHighLevelClient.index(indexRequest);
//获取响应结果
DocWriteResponse.Result result = indexResponse.getResult();
System.out.println(result);
}
/**
* 查询文档
* @throws IOException
*/
@Test
public void getDoc() throws IOException {
// 创建get请求
GetRequest getRequest = new GetRequest(
"xc_course",
"doc",
"AX5LKHYBrcb0-WfhRHh1");
// 查询数据
GetResponse getResponse = restHighLevelClient.get(getRequest);
// 查看是否查询成功
boolean exists = getResponse.isExists();
// 获取查询数据
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();
System.out.println(sourceAsMap);
}
/**
* 更新文档
*/
@Test
public void updateDoc() throws IOException {
// 创建更新
UpdateRequest updateRequest = new UpdateRequest("xc_course", "doc",
"AX5LKHYBrcb0-WfhRHh1");
// 输入你要更新的字段数据
Map<String, String> map = new HashMap<>();
map.put("name", "spring cloud无敌");
// 添加进类型
updateRequest.doc(map);
// 执行更新
UpdateResponse update = restHighLevelClient.update(updateRequest);
// 查看更新状态
RestStatus status = update.status();
System.out.println(status);
}
/**
* 根据id删除文档
* @throws IOException
*/
@Test
public void testDelDoc() throws IOException {
//删除文档id
String id = "__mapping";
//删除索引请求对象
DeleteRequest deleteRequest = new DeleteRequest("xc_course","doc",id);
//响应对象
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest);
//获取响应结果
DocWriteResponse.Result result = deleteResponse.getResult();
System.out.println(result);
}
/**
* 搜索type下的所有记录
*/
@Test
public void testSearchAll() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* 搜索type下的当前页记录
*/
@Test
public void testSearchPage() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
int page = 1;
int size = 1;
// 获取从那条记录开始
int from = (page - 1) * size;
// 从当前记录开始
searchSourceBuilder.from(from);
// 每页展示的记录数
searchSourceBuilder.size(size);
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* TermQuery: 精确查询,在搜索时会整体匹配关键字,不再将关键字分词
*/
@Test
public void testTermQuery() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 搜索精准查询, 不分词
searchSourceBuilder.query(QueryBuilders.termQuery("name","spring"));
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* TermsQuery: 根据id精确匹配
*/
@Test
public void testTermsQuery() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
String[] values = new String[] {"1", "2"};
// 搜索精准查询, 不分词
searchSourceBuilder.query(QueryBuilders.termsQuery("_id",values));
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* MatchQuery: 即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索
*
* query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。
*
* operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件
*/
@Test
public void testMatchQuery() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 搜索字符串分词, operator为or(或)
searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring java").operator(Operator.AND));
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* MatchQuery: 即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索
*
* query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。
*
* 设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表
* 示至少有两个词在文档中要匹配成功
*/
@Test
public void testMatchQueryMinimumShouldMatch() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 搜索字符串分词, 百分比查询
searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架").minimumShouldMatch("80%"));
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* multiQuery,一次可以匹配多个字段
* minimumShouldMatch: 匹配的百分比
* field: 设置字段, 扩大权重
* 字段: 指定要设置权重的字段
* boost: 匹配多个字段时可以提升字段的boost(权重)来提高得分
* @throws IOException
*/
@Test
public void testMultiMatchQuery() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 一次可以匹配多个字段, name, description
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "name","description").minimumShouldMatch("50%").field("name",10));
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* 布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来
*
* must:文档必须匹配must所包括的查询条件,相当于 “AND”
* should:文档应该匹配should所包括的查询条件其 中的一个或多个,相当于 "OR"
* must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”
*
*
* @throws IOException
*/
@Test
public void testBooleanQuery() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 定义MultiMatchQueryBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description").minimumShouldMatch("50%").field("name", 10);
// 在定义termQueryBuilder
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
// 在定义boolQueryBuilder
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 把之前定义的查询条件, 添加到boolQueryBuilder的must里
boolQueryBuilder.must(multiMatchQueryBuilder);
boolQueryBuilder.must(termQueryBuilder);
// 添加boolQueryBuilder的查询条件
searchSourceBuilder.query(boolQueryBuilder);
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* Filter: 过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过
* 虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用
*
* range: 范围过虑,保留大于等于60 并且小于等于100的记录。
*
* term: 项匹配过滤, 保留studymodel等于"201001"的记录
*
* @throws IOException
*/
@Test
public void testFilter() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 定义MultiMatchQueryBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description").minimumShouldMatch("50%").field("name", 10);
// 在定义boolQueryBuilder
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 把之前定义的查询条件, 添加到boolQueryBuilder的must里
boolQueryBuilder.must(multiMatchQueryBuilder);
// 定义过滤器
// 过滤出studymodel字段为201001的记录
boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"));
// 过滤出, price字段值, 大于80小于100的记录
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(80).lte(100));
// 添加boolQueryBuilder的查询条件
searchSourceBuilder.query(boolQueryBuilder);
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* Sort: 可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序
* @throws IOException
*/
@Test
public void testSort() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// 在定义boolQueryBuilder
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 过滤出, price字段值, 大于80小于100的记录
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(80).lte(100));
// 添加boolQueryBuilder的查询条件
searchSourceBuilder.query(boolQueryBuilder);
// 定义排序字段
searchSourceBuilder.sort("studymodel", SortOrder.DESC);
searchSourceBuilder.sort("price", SortOrder.ASC);
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
/**
* Highlight: 高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置
* @throws IOException
*/
@Test
public void testHighlight() throws IOException {
// 搜索请求对象
SearchRequest searchRequest = new SearchRequest("xc_course");
// 设置类型
searchRequest.types("doc");
// 搜索源构建对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
// source源字段过滤
searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"}, new String[]{});
// 定义MultiMatchQueryBuilder
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发框架", "name", "description").minimumShouldMatch("50%").field("name", 10);
// 在定义boolQueryBuilder
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 添加搜索条件到 must中
boolQueryBuilder.must(multiMatchQueryBuilder);
// 过滤出, price字段值, 大于80小于100的记录
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
// 添加boolQueryBuilder的查询条件
searchSourceBuilder.query(boolQueryBuilder);
// 定义排序字段
searchSourceBuilder.sort("price", SortOrder.ASC);
// 高亮设置
HighlightBuilder highlightBuilder = new HighlightBuilder();
// 设置前缀
highlightBuilder.preTags("" );
// 设置后缀
highlightBuilder.postTags("");
// 设置高亮字段
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
// 把highlightBuilder添加到条件里
searchSourceBuilder.highlighter(highlightBuilder);
// 设置搜索源
searchRequest.source(searchSourceBuilder);
// 执行搜索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
// 搜索匹配结果
SearchHits hits = searchResponse.getHits();
// 搜索总记录数
long totalHits = hits.totalHits;
// 匹配度较高的前N个文档
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String name = (String) sourceAsMap.get("name");
// 获取高亮信息
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields != null) {
// 取出高亮字段内容
HighlightField highlightField = highlightFields.get("name");
if (highlightField == null) {
continue;
}
// 获取内容
Text[] texts = highlightField.getFragments();
StringBuilder stringBuilder = new StringBuilder();
for (Text text : texts) {
stringBuilder.append(text.toString());
}
name = stringBuilder.toString();
}
String studymodel = (String) sourceAsMap.get("studymodel");
// 因为上面过滤了该字段, 所有该字段的数据是取不到的
String description = (String) sourceAsMap.get("description");
System.out.println(name);
System.out.println(studymodel);
System.out.println(description);
}
}
}