一、ElasticSearch 简介
中文参考网站https://www.elastic.co/guide/cn/elasticsearch/guide/current/_indexing_employee_documents.html
- Lucene是一套信息检索工具包! jar包!不包含搜索引擎系统!
- 包含的∶索引结构!读写索引的工具!排序,搜索规则…工具类!
- Lucene 和 ElasticSearch 关系︰
ElasticSearch 是基于Lucene做了一些封装和增强 - Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。
二、Elasticsearch vs Solr总结
Elasticsearch 和 Solr 都是基于 Lucene 工具包开发的搜索引擎,建议使用 Elasticsearch(数据量大小对效率影响不高,而 Solr 数据量越大效率越低)
- 1、es基本是开箱即用(解压就可以用!),非常简单。Solr安装略微复杂一丢丢!
- 2、Solr利用Zookeeper进行分布式管理,而Elasticsearch自身带有分布式协调管理功能。
- 3、Solr支持更多格式的数据,比如JSON、XML、CSV,而Elasticsearch 仅支持json文件格式。
- 4、Solr官方提供的功能更多,而Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑~!
- 5、Solr查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;
- ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。
- Solr是传统搜索应用的有力解决方案,但Elasticsearch更适用于新兴的实时搜索应用。
- 6、Solr比较成熟,有一个更大工更成熟的用户、开发和贡献者社区,而Elasticsearch相对开发维护者较少,更新太快,学习使用成本较高。
三、Elasticsearch、head、kibana 安装
1、Elasticsearch 安装
声明:jdk 1.8,最低要求!Elasticsearch 客户端,界面工具
https://www.elastic.co/cn/downloads/elasticsearch ELK (Elasticsearch、Logstash、Kibana)三剑客,解压即用(web 项目,前端环境)
解压目录 目录说明
- bin 启动目录
- config 配置目录
- log4j2.properties 日志配置文件
- jvm.options java 虚拟机配置
- elasticsearch.yml elasticsearch 配置文件,默认 9200 端口,跨域,集群等
- lib 相关 jar
- logs 日志
- modules 功能模块
- plugins 插件
启动 ElasticSearch http://127.0.0.1:9200/
2、安装 ES 数据展示插件 head
下载地址 https://github.com/mobz/elasticsearch-head
①、启动
git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
open http://localhost:9100/
npm install 可能会报错,需要升级 npm 版本,如果 phantomjs 不能安装尝试使用如下命令 npm install phantomjs-prebuilt@2.1.14 --ignore-scripts
–ignore-scripts 参数忽略脚本
②、配置跨域
http://127.0.0.1:9100 连接 http://127.0.0.1:9200 存在跨域,需要配置跨域 打开 H:\ElasticSearch\elasticsearch-7.14.0\config\elasticsearch.yml 追加跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
连接成功 新建索引
3、安装 ES 查询工具 kibana
①、下载启动
下载地址,版本需要和 ElasticSearch 版本一致 https://www.elastic.co/cn/downloads/kibana kibana 配置 bin/kibana.bat 启动
②、访问测试
默认端口 5601 ,http://localhost:5601 汉化: 修改 kibana-7.14.0-windows-x86_64\config\kibana.yml 文件追加 i18n.locale: "zh-CN"
四、ES 概念
和关系数据库对应关系
- NTR:近乎实时的搜索平台。这意味着从索引文档到可搜索之间存在轻微的延迟(通常为一秒)。
- 集群:集群是一个或多个节点(服务器)的集合,它们共同保存您的整个数据并提供跨所有节点的联合索引和搜索功能。默认有一个集群,名字就是 ElasticSearch
- 节点:节点是单个服务器,它是集群的一部分,存储您的数据,并参与集群的索引和搜索功能。
- 索引:就是数据库,索引是具有某些相似特征的文档的集合。
- 文档:一条条数据,最小的索引搜索单位,就是一个 json 对象,fastjson 进行自动转换
- 类型:和 mysql 表类似
- 分片:
- 它允许您水平拆分/缩放您的内容量
- 它允许您跨分片(可能在多个节点上)分布和并行化操作,从而提高性能/吞吐量
- 副本:
- 它在分片/节点发生故障时提供高可用性。出于这个原因,重要的是要注意副本分片永远不会与复制它的原始/主分片在同一节点上分配。
- 它允许您扩展搜索量/吞吐量,因为搜索可以在所有副本上并行执行。
五、倒排索引
正排索引:遍历每个文章,找索引对应关系。根据文章找词 倒排索引:根据倒排索引找到与文章的对应关系。根据词找文章 例一 文档1:tom,cat,dog,study up 文档2:cat,study up,sun,red
其中 1 代表存在,0 代表不存在
词组 | 文档1 | 文档2 |
---|
tom | 1 | 0 | cat | 1 | 1 | dog | 1 | 0 | study up | 1 | 1 | sun | 0 | 1 | red | 0 | 1 |
统计如下
项目 | score |
---|
tom | 文档1 | cat | 文档1,文档2 | dog | 文档1 | study up | 文档1,文档2 | sun | 文档2 | red | 文档2 |
如果索引某个值,可以很快查找到具体的文章
例二 简单的倒排索引 复杂的倒排索引
- 单词ID:记录每个单词的单词编号;
- 单词:对应的单词;
- 文档频率:代表文档集合中有多少个文档包含某个单词
- 倒排列表:包含单词ID及其他必要信息
- DocId:单词出现的文档id
- TF:单词在某个文档中出现的次数
- POS:单词在文档中出现的位置
六、IK分词器插件
1、什么是分词器
将一段中文或英文划分成一个个关键字,在搜索时会把信息进行分词,然后与索引库进行对比,默认将中文每个字拆分为一个词,如“我爱吃饭”—》“我”,“爱”,“吃”,“饭”四个词,这显然不符合要求,需要使用中文分词器 IK 解决问题,中文分词建议使用 IK 分词器。 IK 提供了两个分词算法:ik_smart 和 ik_max_word,ik_smart 最少切分, ik_max_word最细粒度切分
2、下载启动
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.0/elasticsearch-analysis-ik-7.14.0.zip
下载完成解压放在ElasticSearch 的plugins 目录下 H:\ElasticSearch\elasticsearch-7.14.0\plugins,
重启 ElasticSearch 可以看到加载了 IK 插件 也可以使用 elasticsearch-plugin list 看到加载了 ik 插件
3、开启 ES 安全访问功能
测试出现这个,需要开启安全功能参考https://www.elastic.co/guide/en/elasticsearch/reference/7.14/security-minimal-setup.html说明
- elasticsearch.yml 追加 xpack.security.enabled: true
- 启动 ES ,另开一个cmd,输入 elasticsearch-setup-passwords interactive 自定义密码
- kibana.yml 追加 elasticsearch.username: “kibana_system”
- H:\ElasticSearch\kibana-7.14.0-windows-x86_64\bin 目录下,kibana-keystore create 命令新建 kibana-keystore 文件
- 命令 kibana-keystore add elasticsearch.password 添加密码,输入刚才 ES 中自定义的密码
- 重启 kibana,访问 http://localhost:5601,用户名 elastic,密码就是自定义的密码
4、测试 IK 分词算法
①、测试 ik 的 ik_smart 最少切分分词算法
GET _analyze
{
"analyzer": "ik_smart",
"text": ["我喜爱你"]
}
结果如下
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "喜",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "爱你",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
}
]
}
②、测试 ik 的 ik_max_word 最细粒度切分分词算法
GET _analyze
{
"analyzer": "ik_max_word",
"text": ["我喜爱你"]
}
结果如下
{
"tokens" : [
{
"token" : "我",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "喜爱",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "爱你",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
}
]
}
从上面的例子可以看出 IK 两种分词算法,ik_max_word 相比 ik_smart 会有重复的词组,比如 ik_max_word 有 “喜爱“、”爱你”
5、自定义分词器
上面的测试 "我喜爱你"产生的词组没有“喜爱你”,添加一个喜爱你词组
H:\ElasticSearch\elasticsearch-7.14.0\plugins\elasticsearch-analysis-ik-7.14.0\config 目录下新建一个 ye.dic 文件, 其中添加词组 “喜爱你”。注意需要保存文件为 UTF-8 IK 配置文件配置 ye.dic 自定义词组 H:\ElasticSearch\elasticsearch-7.14.0\plugins\elasticsearch-analysis-ik-7.14.0\config\IKAnalyzer.cfg.xml 配置 ye.dic 文件 <entry key="ext_dict">ye.dic</entry> 其中 key="ext_dict"为扩展词典固定些法,ye.dic 为自定义词组文件名,注意:只能有一个 key=“ext_dict” 的 entry 标签
6、重启 ES 和 kibana 测试
重启 ES 可以看到加载了 ye.dic 文件 ik_smart 和 ik_max_word两种算法都正确
七、ElasticSearch 配置 xpack 之后,ElasticSearch-head连接不上
ElasticSearch 配置 xpack 之后,ElasticSearch-head 连接会出现以下问题,意思就是未授权 添加 xpack 设置的用户密码http://localhost:9100/?auth_user=elastic&auth_password=..ye123456 访问 如果是 Linux crul 访问,可以使用 curl -XGET -uelastic:123456 "http://localhost:9200" 会出现如下问题 在 H:\ElasticSearch\elasticsearch-7.14.0\config\elasticsearch.yml 文件中追加 http.cors.allow-headers: Authorization,Content-Type 可以发现连接成功
八、索引操作
1、数据类型
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html binary、 boolean、 Keywords、 Numbers、 Dates、 version、 geo_point 等
2、PUT 创建
7.14 版本不建议指定类型,否则会报警告,请求可以用任意工具发送,不一定适用 kibana
PUT /test/_doc/1 其中 test 为索引名,_doc 为默认类型不用写, 1 为索引 id 可以看到插入成功 创建索引格式 (类似建表语句) 可以看到只有表结构没有数据
3、GET 获取
GET test2
GET test3/_search
如果 自己的文档没有指定字段类型,则会有默认类型
4、POST 修改
查询
GET test3/_search
POST test3/_search
修改
POST /test3/_update/2
{
"doc":{
"name":"夜猫子",
"age":20
}
}
PUT /test3/_doc/2
{
"name":"夜猫子",
"age":18,
"birthday":"2020-1-8"
}
其中 _version 表示修改的次数,result:”update“ 代表修改
5、DELETE 删除
DELETE test2
DELETE test3/_doc/3
九、文档操作
文档的操作同索引一样,也是通过 resultful 风格接口增删改查
带参数查询
GET /test3/_doc/_search?q=name:叶
- _score,max_score 可以用来判断谁更符合
- hits 查询出来的具体文档
1、结果过滤、排序
索引数据如下,注意:排序之后 _score 为 null,不存在权重
- 结果过滤 ----> 指定查询字段,select * 和 select id,name 区别
- 排序 -----> desc 降序,asc 升序
2、分页查询
GET /test3/_search
{
"query":{
"match": {
"birthday":"2020"
}
},
"_source": ["name","age","height"],
"sort": [
{
"age": {
"order": "asc"
},
"height": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
3、多条件查询
注意:match 模糊查询,只支持字符串,数字等格式不支持
- bool:条件查询
- must:条件都要满足,类似 a and b , a&&b
- must_not:条件都不满足 !(a&&b)
- should:满足其已即可 a or b , a || b
4、范围查询过滤器 filter
gt >,gte >=,lt <,lte <= 查询 name 包含 “叶” 或者 age = 28 并且过滤 age >=10 && age<=20
5、filed 多值查询–in
查询 habbit 的多个值,类似 mysql in 加模糊匹配操作
6、精准查询 term
keyword 就是一个字符串,没有被拆分,当你使用 match 是会不用到分词器,所以不支持模糊匹配
①、term 查询 text 类型字段,如果精准查询失败,原因事经过分词器,默认分为一个字一个词 ②、term 查询 text 类型字段,经过分词器,找到 java 对应的词组 ③、term 查询 keyword 类型字段,keyword 不分词,只支持精准查询 ④、term 查询 keyword 类型字段,keyword 不分词,只支持精准查询,查询成功
term 查询多个值和 match 类似
7、match 和 term 区别
- match 查询: text 字段支持模糊查询以及精准匹配,keyword 只支持精准匹配
- trem 查询: text 字段支持分词器分词结果的精准匹配,keyword 只支持精准匹配
8、高亮查询
①、查询高亮
高亮会默认添加 标签
②、自定义高亮标签
自定义高亮字段前缀后缀
十、springboot 集成
1、ES api 简单测试
官方文档,使用 Java REST Client [7.14] https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-initialization.html
①、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
指定版本 elasticsearch 集成版本,尽量修改为本地 elasticsearch 版本,pom文件中指定版本,覆盖项目版本
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.14.0</elasticsearch.version>
</properties>
②、yml 配置 ElasticSearch
如果是集群可以配置多个服务器 Java代码配置
@Configuration
public class ElasticSearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestClientBuilder restClientBuilder = RestClient.builder(
new HttpHost("localhost", 9200, "http")
);
return new RestHighLevelClient(restClientBuilder);
}
}
yml 配置
spring:
elasticsearch:
rest:
uris: http://127.0.0.1:9200
username: elastic
password: ..ye123456
2、索引的增删改查
@Autowired
RestHighLevelClient restHighLevelClient;
@Test
void createIndex() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest("test_es_api");
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
@Test
void existIndex() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest("test_es_api");
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
@Test
void deleteIndex() throws IOException {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("test_es_api");
AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(delete);
}
3、文档增删改查
①、单文档CRUD
@Test
void addDoc() throws IOException {
User user = new User("小林子", 25);
IndexRequest indexRequest = new IndexRequest("test_user");
indexRequest.id("1");
indexRequest.timeout("1s");
String s = JSON.toJSONString(user);
indexRequest.source(s, XContentType.JSON);
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.status());
System.out.println(indexResponse);
}
@Test
void exitsDoc() throws IOException {
GetRequest getRequest = new GetRequest("test_user","1");
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
@Test
void getDocData() throws IOException {
GetRequest getRequest = new GetRequest("test_user", "1");
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
Map<String, Object> source = getResponse.getSource();
System.out.println(source.get("name"));
System.out.println(source.get("age"));
System.out.println(getResponse.getVersion());
System.out.println(getResponse.getSourceAsString());
System.out.println(getResponse);
}
@Test
void updateDocData() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("test_user","1");
updateRequest.timeout("1s");
HashMap<String, Object> stringObjectHashMap = new HashMap<>();
stringObjectHashMap.put("name","叶灵芸");
stringObjectHashMap.put("age",89);
updateRequest.doc(stringObjectHashMap);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
System.out.println(updateResponse);
}
@Test
void deleteDocData() throws IOException {
DeleteRequest test_user = new DeleteRequest("test_user", "5");
DeleteResponse delete = restHighLevelClient.delete(test_user, RequestOptions.DEFAULT);
System.out.println(delete.status());
System.out.println(delete);
}
②、批量文档CRUD
批量删除、更新类似,只需要修改 for 循环中,new IndexRequest()、new DeleteRequest、new UpdateRequest()
@Test
void testBulk() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
ArrayList<User> users = new ArrayList<>();
users.add(new User("张三",56));
users.add(new User("李四",23));
users.add(new User("王五",99));
users.add(new User("张麻子",33));
for (User user : users) {
bulkRequest.add(new IndexRequest("test_user").id("").source(JSON.toJSONString(user),XContentType.JSON).timeout("1s"));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
System.out.println(bulkResponse.status());
System.out.println(bulkResponse.hasFailures());
System.out.println(bulkResponse);
}
@Test
void testBulkDelete() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
String[] strings = new String[]{"lxUuh3sB4XNJgblKGvMz","lhUuh3sB4XNJgblKGvMz","lxUuh3sB4XNJgblKGvMz"};
for (String string : strings) {
bulkRequest.add(new DeleteRequest("test_user",string).timeout("1s"));
}
BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulk.hasFailures());
System.out.println(bulk);
}
4、高级查询
测试表数据
①、模糊查询、多值查询、结果筛选指定字段
kibana 方式,term不支持多值查询
代码实现
@Test
void searchData() throws IOException {
SearchRequest searchRequest = new SearchRequest("test_student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "1 2 5");
searchSourceBuilder.query(queryBuilder);
searchSourceBuilder.fetchSource(new String[]{"name","birth"},new String[]{"age"});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
结果
②、高亮查询
kibana 调用 java 代码实现
@Test
void testHighLight() throws IOException {
SearchRequest searchRequest = new SearchRequest("test_student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "1 2 5");
searchSourceBuilder.query(matchQueryBuilder);
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.preTags("<p class='key' style='color:red'>");
highlightBuilder.postTags("</p>");
searchSourceBuilder.highlighter(highlightBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
System.out.println(hit.getHighlightFields());
}
}
结果
③、多字段查询
kibana 接口 代码实现
@Test
void testManyFiled() throws IOException {
SearchRequest searchRequest = new SearchRequest("test_student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "1 2 5");
MatchQueryBuilder queryBuilder2 = QueryBuilders.matchQuery("age", "30");
searchSourceBuilder.query(QueryBuilders.boolQuery().must(queryBuilder).must(queryBuilder2));
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(search.getHits().getHits()[0].getSourceAsMap());
}
④、排序、分页
kibana 接口 Java代码实现
@Test
void testOrder() throws IOException {
SearchRequest searchRequest = new SearchRequest("test_student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "小");
searchSourceBuilder.query(matchQueryBuilder);
FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("age");
fieldSortBuilder.order(SortOrder.DESC);
FieldSortBuilder fieldSortBuilder2 = SortBuilders.fieldSort("height");
fieldSortBuilder2.order(SortOrder.ASC);
searchSourceBuilder.sort(Arrays.asList(fieldSortBuilder,fieldSortBuilder2));
searchSourceBuilder.from(0);
searchSourceBuilder.size(3);
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
结果
十一、总结 Java 写法
- 根据 kibana API 接口实现Java代码
- GET /test/_search ------> new SearchRequest()
- POST /test/_update/2 ----------> new UpdateRequest()
- API 请求里写的参数,根据层级关系在代码实现请求参数和获取想要的结果
- 相同层级之间可以使用链式编程
- 从最外层一层一层解析请求编写 Java 代码
- 条件构建器,query 对应 QueryBuilders 工具方法,sort 对应 SortBuilders 工具方法
数据表
下面请求多字段查询,分页、排序高亮、多条件,结果过滤
GET /test_student/_search
{
"query": {
"bool": {
"must": [
{"match": {"name": "小" }},
{"match": {"address": "西" }}
],
"filter": [
{"range": {
"height": {"gte": 150,"lte": 200}
}},
{"range": {
"age": {"gt": 15,"lt": 35}
}}
]
}
},
"sort": [
{ "age": {"order": "desc"}},
{"height": { "order": "asc"}}
],
"highlight": {
"pre_tags":"<a>",
"post_tags":"</a>",
"fields": {
"name": {},
"address": {}
}
},
"_source": ["name","name","address","height","birth"],
"from": 0,
"size": 4
}
代码实现
@Test
void testOrder() throws IOException {
SearchRequest searchRequest = new SearchRequest("test_student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "小");
MatchQueryBuilder matchQueryBuilder2 = QueryBuilders.matchQuery("address", "西");
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
rangeQueryBuilder.gte(15);
rangeQueryBuilder.lte(35);
RangeQueryBuilder rangeQueryBuilder2 = QueryBuilders.rangeQuery("height");
rangeQueryBuilder.gte("150");
rangeQueryBuilder.lte("200");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().must(matchQueryBuilder).must(matchQueryBuilder2);
BoolQueryBuilder boolQueryBuilder1 = boolQueryBuilder.filter(rangeQueryBuilder).filter(rangeQueryBuilder1);
searchSourceBuilder.query(boolQueryBuilder1);
FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("age");
fieldSortBuilder.order(SortOrder.DESC);
FieldSortBuilder fieldSortBuilder2 = SortBuilders.fieldSort("height");
fieldSortBuilder2.order(SortOrder.ASC);
searchSourceBuilder.sort(Arrays.asList(fieldSortBuilder,fieldSortBuilder2));
searchSourceBuilder.from(0);
searchSourceBuilder.size(3);
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<a>");
highlightBuilder.postTags("</a>");
highlightBuilder.field("name").field("address");;
searchSourceBuilder.highlighter(highlightBuilder);
searchSourceBuilder.fetchSource(new String[]{"name","address","age","height","birth"},new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
System.out.println(hit.getHighlightFields());
}
}
结果
|