下载地址
Elasticsearch 7.17.6
Kibana 7.17.6
ES 配置
配置ES的JDK11,指向解压包
ES_JAVA_HOME
修改ES启动的运存
修改config目录里的 jvm.options 文件
防止开发时候电脑太卡
-Xms128m
-Xmx512m
启动kibana
bin 目录下的 kibana.bat ,启动时间比较久
查看node版本
设置为中文
config目录下单 kibana.yml
最后一行加上,然后重启服务
i18n.locale: "zh-CN"
安装 IK 分词
下载地址
解压到目录里 elasticsearch-7.17.6\plugins\ik
安装好后重启ES服务
配置自己的词典
1.进入 elasticsearch-7.17.6\plugins\ik\config 目录,随便复制一个dic后缀的文件,修改名字为 mydic.dic。
2.编辑 mydic.dic 文件。
3.重启ES服务
4.智能分词里就有自己添加的词
去掉需要密码的提示
目录 elasticsearch-7.17.6\config\elasticsearch.yml 最后一行加上:
xpack.security.enabled: false
加上日志输出请求
application.yml末尾加上
logging:
level:
tracer: TRACE
kibana 控制台
# 查看健康状态
GET /_cat/health?v
# 查看节点
GET /_cat/nodes?v
# 查看索引
GET /_cat/indices?v
# 新建索引
PUT /my_test
# 删除索引
DELETE /my_test
# ik 分词测试
GET /_analyze?pretty
{
"analyzer" : "ik_max_word",
"text": "中华人民共和国国歌"
}
ES直接操作学习
融入JAVA 项目
官方文档
JAVA代码样例
public class ElasticsearchRepositoryTest extends BaseTest {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private GoodsRepository goodsEsRepository;
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 导入测试数据,从mysql中导入测试数据至es
*/
@Test
public void importAllData() {
// 查询所有数据
List<Goods> lists = goodsMapper.findAll();
// 保存所有数据只ES中
goodsEsRepository.saveAll(lists);
System.out.println("ok");
}
/**
* 添加文档
*/
@Test
public void save() {
// PUT /goods/_doc/1?timeout=1m
// {"_class":"com.sky.demo.domain.Goods","id":1,"title":"Apple iPhone 13 ProMax 5G全网通手机","price":8999.0,"stock":100,"saleNum":1,"categoryName":"手机","brandName":"Apple","status":0,"createTime":"2022-09-23 07:53:43"}
Goods goods = new Goods(1L, "Apple iPhone 13 ProMax 5G全网通手机", new BigDecimal(8999), 100, 1, "手机", "Apple", 0, new Date());
goodsEsRepository.save(goods);
}
/**
* 批量添加数据
*/
@Test
public void saveAll() {
List<Goods> goodsList = new ArrayList<>();
goodsList.add(new Goods(2L, "title2", new BigDecimal(12), 1, 1, "category2", "brandName2", 0, new Date()));
goodsList.add(new Goods(3L, "title3", new BigDecimal(12), 1, 1, "category3", "brandName3", 0, new Date()));
goodsList.add(new Goods(4L, "title4", new BigDecimal(12), 1, 1, "category4", "brandName4", 0, new Date()));
goodsEsRepository.saveAll(goodsList);
}
/**
* 根据编号查询
*/
@Test
public void findById() {
// GET '/goods/_doc/536563'
Optional<Goods> optional = goodsEsRepository.findById(536563L);
System.out.println(optional.orElse(null));
}
/**
* 查询所有
*
*/
@Test
public void findAll() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
Iterable<Goods> list = goodsEsRepository.findAll();
for (Goods item : list) {
System.out.println(item);
}
}
/**
* 分页查询
*/
@Test
public void findAllByPage() {
// 数据太多了分页查询
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from":0,"size":10
// }
PageRequest pageRequest = PageRequest.of(0, 10);
Iterable<Goods> list = goodsEsRepository.findAll(pageRequest);
for (Goods item : list) {
System.out.println(item);
}
}
/**
* 排序查询
*/
@Test
public void findAllBySort() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from":0,"size":10
// ,"sort":[{"price":{"order":"desc","mode":"min"}}]
// }
Iterable<Goods> list = goodsEsRepository.findAll(Sort.by(Sort.Direction.DESC, "price"));
for (Goods item : list) {
System.out.println(item);
}
}
/**
* 根据ID批量查询
*/
@Test
public void findAllById() {
// GET /_mget
// {
// "docs": [{
// "_index": "goods",
// "_id": "536563"
// }, {
// "_index": "goods",
// "_id": "562379"
// }, {
// "_index": "goods",
// "_id": "605616"
// }, {
// "_index": "goods",
// "_id": "635906"
// }]
// }
List<Long> asList = Arrays.asList(536563L, 562379L, 605616L, 635906L);
Iterable<Goods> list = goodsEsRepository.findAllById(asList);
for (Goods item : list) {
System.out.println(item);
}
}
/**
* 统计数量
*/
@Test
public void count() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {"from":0,"size":0}
System.out.println(goodsEsRepository.count());
}
/**
* 根据编号判断文档是否存在
*/
@Test
public void existsById() {
// GET /goods/_doc/536563?_source=false
System.out.println(goodsEsRepository.existsById(536563L));
}
/**
* 删除文档
*/
@Test
public void delete() {
// DELETE /goods/_doc/1?timeout=1m
goodsEsRepository.findById(1L).ifPresent(goods -> goodsEsRepository.delete(goods));
}
/**
* 删除所有文档
*/
@Test
public void deleteAll() {
goodsEsRepository.deleteAll();
}
/**
* 根据编号批量删除文档
*/
@Test
public void deleteAllByIds() {
goodsEsRepository.deleteAll(goodsEsRepository.findAllById(Arrays.asList(1L, 2L, 3L)));
}
/**
* 根据编号删除文档
*/
@Test
public void deleteById() {
// DELETE 'http://127.0.0.1:9200/goods/_doc/4?timeout=1m'
goodsEsRepository.deleteById(4L);
}
/*
自定义方法:
Spring Data 的另一个强大功能,是根据方法名称自动实现功能。比如:你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。当然,方法名称要符合一定的约定:
https://www.cnblogs.com/tanghaorong/p/16365684.html
/**
* 自定义方法:根据标题查询
*/
@Test
public void findByTitle() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "query": {
// "bool": {
// "must": [{
// "query_string": {
// "query": "华为",
// "fields": ["title^1.0"]
// }
// }]
// }
// }
// }
goodsEsRepository.findByTitle("华为").forEach(System.out::println);
}
/**
* 自定义方法:根据价格区间查询
*/
@Test
public void findByPriceBetween() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "query": {
// "bool": {
// "must": [{
// "range": {
// "price": {
// "from": 3000,
// "to": 5000,
// "include_lower": true,
// "include_upper": true,
// "boost": 1.0
// }
// }
// }]
// }
// }
// }
goodsEsRepository.findByPriceBetween(new BigDecimal("3000"), new BigDecimal("5000")).forEach(System.out::println);
}
/**
* 精确查询(termQuery)
*/
@Test
public void termQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {"from":0,"size":10,"query":{"term":{"categoryName":{"value":"手机","boost":1.0}}},"version":true,"explain":false}
//查询条件(词条查询:对应ES query里的term)
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("categoryName", "手机");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(termQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = searchHits.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
searchHits.getSearchHits().stream().map(SearchHit<Goods>::getContent).forEach(System.out::println);
}
/**
* terms:多个查询内容在一个字段中进行查询
*/
@Test
public void termsQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {"from":0,"size":10,"query":{"terms":{"categoryName":["手机","平板电视"],"boost":1.0}},"version":true,"explain":false}
//查询条件(词条查询:对应ES query里的terms)
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("categoryName", "手机", "平板电视");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(termsQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = searchHits.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
searchHits.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
@Test
public void matchQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match": {
// "title": {
// "query": "Apple IPhone 白色",
// "operator": "AND",
// "analyzer": "ik_smart",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// },
// "version": true,
// "explain": false
// }
//
//查询条件(词条查询:对应ES query里的match)
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "Apple IPhone 白色").analyzer("ik_smart").operator(Operator.AND);
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(matchQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = search.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* match_all:查询全部。
* 默认查询10条
*/
@Test
public void matchAllQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match_all": {
// "boost": 1
// }
// },
// "version": true,
// "explain": false
// }
//查询条件(词条查询:对应ES query里的match)
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = search.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* match_phrase:短语查询,在match的基础上进一步查询词组,可以指定slop分词间隔。
* 默认查询10条
*/
@Test
public void matchPhraseQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match_phrase": {
// "title": {
// "query": "华为",
// "slop": 0,
// "zero_terms_query": "NONE",
// "boost": 1
// }
// }
// },
// "version": true,
// "explain": false
// }
//查询条件(词条查询:对应ES query里的match_all)
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("title", "华为");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(matchPhraseQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = search.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* multi_match:多字段查询,使用相当的灵活,可以完成match_phrase和match_phrase_prefix的工作。
*/
@Test
public void multiMatchQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "multi_match": {
// "query": "华为和Apple",
// "fields": [
// "categoryName^1.0",
// "title^1.0"
// ],
// "type": "best_fields",
// "operator": "OR",
// "analyzer": "ik_smart",
// "slop": 0,
// "prefix_length": 0,
// "max_expansions": 50,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "fuzzy_transpositions": true,
// "boost": 1
// }
// },
// "version": true,
// "explain": false
// }
//查询条件(词条查询:对应ES query里的multi_match)
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("华为和Apple", "title", "categoryName").analyzer("ik_smart");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(multiMatchQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = search.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 通配符查询
* <p>
* *:表示多个字符(0个或多个字符)
* ?:表示单个字符
*/
@Test
public void wildcardQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "wildcard": {
// "title": {
// "wildcard": "华为*",
// "boost": 1
// }
// }
// },
// "version": true,
// "explain": false
// }
//查询条件
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery( "title","华为*");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(wildcardQueryBuilder).build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
long totalHits = search.getTotalHits();
System.out.println("totalHits = " + totalHits);
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 排序查询(sort)
* 匹配查询符合条件的所有数据,并设置分页
*/
@Test
public void sort() {
//查询条件(词条查询:对应ES query里的match)
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match_all": {
// "boost": 1
// }
// },
// "version": true,
// "explain": false,
// "sort": [
// {
// "price": {
// "order": "desc"
// }
// }
// ]
// }
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("price").order(SortOrder.DESC);
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQueryBuilder)
.withSorts(fieldSortBuilder)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 分页查询(page)
*/
@Test
public void pageQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 5,
// "query": {
// "match_all": {
// "boost": 1
// }
// },
// "version": true,
// "explain": false,
// "sort": [
// {
// "price": {
// "order": "desc"
// }
// }
// ]
// }
//查询条件
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("price").order(SortOrder.DESC);
// 分页数据
PageRequest pageRequest = PageRequest.of(0, 5);
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQueryBuilder)
.withSorts(fieldSortBuilder)
.withPageable(pageRequest)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数,当前页,每页大小
System.out.println("totalHits = " + search.getTotalHits());
System.out.println("pageNumber = " + pageRequest.getPageNumber());
System.out.println("pageSize = " + pageRequest.getPageSize());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 滚动查询所有数据
*/
@Test
public void scrollQuery1() {
// 设置每页数据量
int pageSize = 10;
MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();//条件
FieldSortBuilder sortBuilder = new FieldSortBuilder("id").order(SortOrder.ASC);//排序
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder).withSorts(sortBuilder).build();
nativeSearchQuery.setMaxResults(pageSize);// 设置每页数据量
long scrollTimeInMillis = 60 * 1000;//设置缓存内数据的保留时间,不要把缓存时时间设置太长,否则占用内存。
// 缓存第一页符合搜索条件的数据
SearchScrollHits<Goods> searchScrollHits = elasticsearchRestTemplate.searchScrollStart(scrollTimeInMillis, nativeSearchQuery, Goods.class, IndexCoordinates.of("goods"));
String scrollId = searchScrollHits.getScrollId();
int scrollTime = 1;
while (searchScrollHits.hasSearchHits()) {// 判断searchScrollHits中是否有命中数据,如果为空,则表示已将符合查询条件的数据全部遍历完毕
System.out.println("第" + scrollTime + "页数据,数据总数:" + searchScrollHits.getSearchHits().size());
for (SearchHit<Goods> searchHit : searchScrollHits.getSearchHits()) {// 从缓存中读取数据
Goods goods = searchHit.getContent();
System.out.println(goods);
}
// 根据上次搜索结果scroll_id进入下一页数据搜索
searchScrollHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, scrollTimeInMillis, Goods.class, IndexCoordinates.of("goods"));//该方法执行后将重新刷新快照保留时间
scrollId = searchScrollHits.getScrollId();
scrollTime = scrollTime + 1;
}
List<String> scrollIds = new ArrayList<>();
scrollIds.add(scrollId);
// DELETE 'http://127.0.0.1:9200/_search/scroll' -d '{"scroll_id":["FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnZndHRsM0lsU3VPQ0dLQnVwY0V4UlEAAAAAAAAJXhZ4MTI3QUpXYVEtbWtjVU1WQ0d6S1Vn"]}'
elasticsearchRestTemplate.searchScrollClear(scrollIds);// 清除 scroll
}
/**
* 根据查询条件滚动查询
* 可以用来解决深度分页查询问题
*/
@Test
public void scrollQuery2() {
// 假设用户想获取第70页数据,其中每页10条
int pageNo = 70;
int pageSize = 10;
// 构建查询条件
MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
FieldSortBuilder sortBuilder = new FieldSortBuilder("id").order(SortOrder.ASC);//排序
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withSorts(sortBuilder)
.build();
nativeSearchQuery.setMaxResults(pageSize);// 设置每页数据量
long scrollTimeInMillis = 60 * 1000;//设置缓存内数据的保留时间
//1、缓存第一页符合搜索条件的数据
// GET /goods/_search?scroll=60000ms&typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match_all": {
// "boost": 1
// }
// },
// "version": true,
// "explain": false,
// "sort": [
// {
// "id": {
// "order": "asc"
// }
// }
// ]
// }
SearchScrollHits<Goods> searchScrollHits = elasticsearchRestTemplate.searchScrollStart(scrollTimeInMillis, nativeSearchQuery, Goods.class, IndexCoordinates.of("goods"));
String scrollId = searchScrollHits.getScrollId();
int scrollTime = 1;
// 判断searchScrollHits中是否有命中数据,如果为空,则表示已将符合查询条件的数据全部遍历完毕
while (searchScrollHits.hasSearchHits() && scrollTime < pageNo) {
// 根据上次搜索结果scroll_id进入下一页数据搜索
// POST /_search/scroll
// {
// "scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnZndHRsM0lsU3VPQ0dLQnVwY0V4UlEAAAAAAAASqhZ4MTI3QUpXYVEtbWtjVU1WQ0d6S1Vn",
// "scroll": "60000ms"
// }
searchScrollHits = elasticsearchRestTemplate.searchScrollContinue(scrollId, scrollTimeInMillis, Goods.class, IndexCoordinates.of("goods"));//该方法执行后会重新刷新快照保留时间
scrollId = searchScrollHits.getScrollId();
scrollTime = scrollTime + 1;
}
List<String> scrollIds = new ArrayList<>();
scrollIds.add(scrollId);
// 清除 scroll
// DELETE /_search/scroll
// {
// "scroll_id": [
// "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnZndHRsM0lsU3VPQ0dLQnVwY0V4UlEAAAAAAAAgiBZ4MTI3QUpXYVEtbWtjVU1WQ0d6S1Vn"
// ]
// }
// 成功时返回
// {
// "succeeded" : true,
// "num_freed" : 1
// }
elasticsearchRestTemplate.searchScrollClear(scrollIds);
//4、 从缓存中读取数据
for (SearchHit<Goods> searchHit : searchScrollHits.getSearchHits()) {
Goods goods = searchHit.getContent();
System.out.println(goods);
}
}
/**
* 范围查询(range)
*/
@Test
public void range() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "range": {
// "price": {
// "from": 1000,
// "to": 2000,
// "include_lower": true,
// "include_upper": true,
// "boost": 1
// }
// }
// },
// "version": true,
// "explain": false
// }
//查询条件
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").from(1000).to(2000);
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(rangeQueryBuilder)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* boolQuery 查询
*/
@Test
public void boolQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "bool": {
// "must": [
// {
// "match": {
// "title": {
// "query": "金立",
// "operator": "OR",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// },
// {
// "match": {
// "categoryName": {
// "query": "手机",
// "operator": "OR",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// }
// ],
// "filter": [
// {
// "range": {
// "price": {
// "from": 1000,
// "to": 2000,
// "include_lower": false,
// "include_upper": false,
// "boost": 1
// }
// }
// }
// ],
// "adjust_pure_negative": true,
// "boost": 1
// }
// },
// "version": true,
// "explain": false
// }
//查询条件(词条查询:对应ES query里的match)
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("title", "金立"))
.must(QueryBuilders.matchQuery("categoryName", "手机"))
.filter(QueryBuilders.rangeQuery("price").gt(1000).lt(2000));
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* queryStringQuery查询
* 案例:查询出必须包含 华为手机 词语的商品信息
*/
@Test
public void queryStringQuery() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "query_string": {
// "query": "华为手机",
// "fields": [],
// "type": "best_fields",
// "default_operator": "and",
// "max_determinized_states": 10000,
// "enable_position_increments": true,
// "fuzziness": "AUTO",
// "fuzzy_prefix_length": 0,
// "fuzzy_max_expansions": 50,
// "phrase_slop": 0,
// "escape": false,
// "auto_generate_synonyms_phrase_query": true,
// "fuzzy_transpositions": true,
// "boost": 1
// }
// },
// "version": true,
// "explain": false
// }
// 创建 queryString 查询构建器
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("华为手机").defaultOperator(Operator.AND);
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(queryStringQueryBuilder)
.build();
// 执行查询,然后处理响应结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 过滤source获取部分字段内容
*/
@Test
public void sourceFilter() {
//查询条件(词条查询:对应ES query里的match)
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("title", "金立"))
.must(QueryBuilders.matchQuery("categoryName", "手机"))
.filter(QueryBuilders.rangeQuery("price").gt(1000).lt(2000));
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "bool": {
// "must": [
// {
// "match": {
// "title": {
// "query": "金立",
// "operator": "OR",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// },
// {
// "match": {
// "categoryName": {
// "query": "手机",
// "operator": "OR",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// }
// ],
// "filter": [
// {
// "range": {
// "price": {
// "from": 1000,
// "to": 2000,
// "include_lower": false,
// "include_upper": false,
// "boost": 1
// }
// }
// }
// ],
// "adjust_pure_negative": true,
// "boost": 1
// }
// },
// "version": true,
// "explain": false,
// "_source": {
// "includes": [
// "title",
// "categoryName"
// ],
// "excludes": []
// }
// }
// 不需要获取source结果集
SourceFilter sourceFilter = new FetchSourceFilterBuilder().withIncludes("title", "categoryName").build();
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder)
.withSourceFilter(sourceFilter)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(SearchHit::getContent).forEach(System.out::println);
}
/**
* 高亮查询
*/
@Test
public void highlightBuilder() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "query": {
// "match": {
// "title": {
// "query": "三星手机",
// "operator": "OR",
// "prefix_length": 0,
// "max_expansions": 50,
// "fuzzy_transpositions": true,
// "lenient": false,
// "zero_terms_query": "NONE",
// "auto_generate_synonyms_phrase_query": true,
// "boost": 1
// }
// }
// },
// "version": true,
// "explain": false,
// "highlight": {
// "pre_tags": [
// "<font color='red'>"
// ],
// "post_tags": [
// "</font>"
// ],
// "fields": {
// "title": {}
// }
// }
// }
//查询条件(词条查询:对应ES query里的match)
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "三星手机");
//设置高亮三要素 field: 你的高亮字段 // preTags :前缀 // postTags:后缀
HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").preTags("<font color='red'>").postTags("</font>");
//创建查询条件构建器SearchSourceBuilder(对应ES外面的大括号)
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(matchQueryBuilder)
.withHighlightBuilder(highlightBuilder)
.build();
//查询,获取查询结果
SearchHits<Goods> search = elasticsearchRestTemplate.search(nativeSearchQuery, Goods.class);
//获取总记录数
System.out.println("totalHits = " + search.getTotalHits());
//获取值返回
search.getSearchHits().stream().map(searchHit -> {
//获得结果实体
Goods goods = searchHit.getContent();
//所有高亮结果
Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
//遍历高亮结果
for (Map.Entry<String, List<String>> stringListEntry : highlightFields.entrySet()) {
String key = stringListEntry.getKey();
//获取实体反射类
Class<?> aClass = goods.getClass();
try {
//获取该实体属性
Field declaredField = aClass.getDeclaredField(key);
//权限为私的 解除!
declaredField.setAccessible(true);
//替换,把高亮字段替换到这个实体对应的属性值上
declaredField.set(goods, stringListEntry.getValue().get(0));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
return goods;
}).forEach(System.out::println);
}
/**
* 案例:分别获取最贵的商品和获取最便宜的商品
*/
@Test
public void aggMetric() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "_source": {
// "includes": [],
// "excludes": []
// },
// "aggregations": {
// "maxPrice": {
// "max": {
// "field": "price"
// }
// },
// "minPrice": {
// "min": {
// "field": "price"
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 聚合条件
queryBuilder.withAggregations(AggregationBuilders.max("maxPrice").field("price")
,AggregationBuilders.min("minPrice").field("price"));
// queryBuilder.addAggregation(AggregationBuilders.max("maxPrice").field("price"));
// queryBuilder.addAggregation(AggregationBuilders.min("minPrice").field("price"));
queryBuilder.withSourceFilter(new FetchSourceFilterBuilder().build());
//查询,获取查询结果
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
//获取聚合结果
Aggregations aggregations = (Aggregations)searchHits.getAggregations().aggregations();
assert aggregations != null;
//打印聚合结果
ParsedMax max = aggregations.get("maxPrice");
System.out.println("最贵的价格:" + max.getValue());
ParsedMin min = aggregations.get("minPrice");
System.out.println("最便宜的价格:" + min.getValue());
}
/**
* 根据商品分类聚合查询
*/
@Test
public void aggBucket() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "_source": {
// "includes": [],
// "excludes": []
// },
// "aggregations": {
// "aggCategoryName": {
// "terms": {
// "field": "categoryName",
// "size": 10,
// "min_doc_count": 1,
// "shard_min_doc_count": 0,
// "show_term_doc_count_error": false,
// "order": [
// {
// "_count": "desc"
// },
// {
// "_key": "asc"
// }
// ]
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 聚合条件
queryBuilder.withAggregations(AggregationBuilders.terms("aggCategoryName").field("categoryName").size(10));
queryBuilder.withSourceFilter(new FetchSourceFilterBuilder().build());
//查询,获取查询结果
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
//获取聚合结果
// Aggregations aggregations = searchHits.getAggregations();
// assert aggregations != null;
// ParsedStringTerms aggCategoryName = aggregations.get("aggCategoryName");
// //打印聚合结果
// System.out.println(aggCategoryName.getBuckets());
// for (Terms.Bucket bucket : aggCategoryName.getBuckets()) {
// System.out.println(bucket.getKeyAsString() + "====" + bucket.getDocCount());
//
// }
System.out.println(searchHits.getAggregations());
}
/**
* 根据价格区间分组查询
*/
@Test
public void aggRange() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "_source": {
// "includes": [],
// "excludes": []
// },
// "aggregations": {
// "priceRange": {
// "range": {
// "field": "price",
// "ranges": [
// {
// "to": 1000
// },
// {
// "from": 1000,
// "to": 3000
// },
// {
// "from": 3000
// }
// ],
// "keyed": false
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
queryBuilder.withAggregations(AggregationBuilders.range("priceRange").field("price").addUnboundedTo(1000).addRange(1000, 3000).addUnboundedFrom(3000));
queryBuilder.withSourceFilter(new FetchSourceFilterBuilder().build());
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
// 获取聚合信息
Aggregations aggregations =(Aggregations) searchHits.getAggregations().aggregations();
assert aggregations != null;
ParsedRange priceRange = aggregations.get("priceRange");
//获取总记录数
System.out.println("totalHits = " + searchHits.getTotalHits());
//获取值返回
for (Range.Bucket bucket : priceRange.getBuckets()) {
System.out.println(bucket.getKeyAsString() + "====" + bucket.getDocCount());
}
}
/**
* 根据日期分组查询出商品创建日期在"2017-09" - "2017-10" 之间的数据
*/
@Test
public void aggDateRange() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "_source": {
// "includes": [],
// "excludes": []
// },
// "aggregations": {
// "dateRange": {
// "date_range": {
// "field": "createTime",
// "format": "yyy-MM",
// "ranges": [
// {
// "from": "2017-09",
// "to": "2017-10"
// }
// ],
// "keyed": false
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// range查询包左不包右,即:[1,10)
queryBuilder.withAggregations(AggregationBuilders.dateRange("dateRange").field("createTime").format("yyy-MM").addRange("2017-09", "2017-10"));
queryBuilder.withSourceFilter(new FetchSourceFilterBuilder().build());
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
// 获取聚合信息
Aggregations aggregations = (Aggregations)searchHits.getAggregations().aggregations();
assert aggregations != null;
ParsedDateRange priceRange = aggregations.get("dateRange");
//获取总记录数
System.out.println("totalHits = " + searchHits.getTotalHits());
//获取值返回
for (Range.Bucket bucket : priceRange.getBuckets()) {
System.out.println(bucket.getKeyAsString() + "====" + bucket.getDocCount());
}
}
/**
* 根据品牌聚合获取出每个品牌的平均价格
*/
@Test
public void subAgg() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "aggregations": {
// "brandNameAgg": {
// "terms": {
// "field": "brandName",
// "size": 10,
// "min_doc_count": 1,
// "shard_min_doc_count": 0,
// "show_term_doc_count_error": false,
// "order": [
// {
// "_count": "desc"
// },
// {
// "_key": "asc"
// }
// ]
// },
// "aggregations": {
// "avgPrice": {
// "avg": {
// "field": "price"
// }
// }
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
queryBuilder.withAggregations(AggregationBuilders.terms("brandNameAgg").field("brandName")
.subAggregation(AggregationBuilders.avg("avgPrice").field("price")));
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
// 获取聚合信息
Aggregations aggregations = (Aggregations)searchHits.getAggregations().aggregations();
assert aggregations != null;
ParsedStringTerms brandeNameAgg = aggregations.get("brandNameAgg");
//获取总记录数
System.out.println("totalHits = " + searchHits.getTotalHits());
//获取值返回
for (Terms.Bucket bucket : brandeNameAgg.getBuckets()) {
// 获取聚合后的品牌名称
String brandName = bucket.getKeyAsString();
// 获取聚合命中的文档数量
long docCount = bucket.getDocCount();
// 获取聚合后的品牌的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象
ParsedAvg avgPrice = bucket.getAggregations().get("avgPrice");
System.out.println(brandName + "======" + avgPrice.getValue() + "======" + docCount);
}
}
/**
* 根据商品分类聚合,获取每个商品类的平均价格,并且在商品分类聚合之上子聚合每个品牌的平均价格
*/
@Test
public void subSubAgg() {
// GET /goods/_search?typed_keys=true&max_concurrent_shard_requests=5&search_type=query_then_fetch&batched_reduce_size=512
// {
// "from": 0,
// "size": 10,
// "version": true,
// "explain": false,
// "aggregations": {
// "categoryNameAgg": {
// "terms": {
// "field": "categoryName",
// "size": 10,
// "min_doc_count": 1,
// "shard_min_doc_count": 0,
// "show_term_doc_count_error": false,
// "order": [
// {
// "_count": "desc"
// },
// {
// "_key": "asc"
// }
// ]
// },
// "aggregations": {
// "categoryNameAvgPrice": {
// "avg": {
// "field": "price"
// }
// },
// "brandNameAgg": {
// "terms": {
// "field": "brandName",
// "size": 10,
// "min_doc_count": 1,
// "shard_min_doc_count": 0,
// "show_term_doc_count_error": false,
// "order": [
// {
// "_count": "desc"
// },
// {
// "_key": "asc"
// }
// ]
// },
// "aggregations": {
// "brandNameAvgPrice": {
// "avg": {
// "field": "price"
// }
// }
// }
// }
// }
// }
// }
// }
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 注意这里聚合写的位置不要写错,很容易搞混,错一个括号就不对了
queryBuilder.withAggregations(
AggregationBuilders.terms("categoryNameAgg").field("categoryName")
.subAggregation(AggregationBuilders.avg("categoryNameAvgPrice").field("price"))
.subAggregation(AggregationBuilders.terms("brandNameAgg").field("brandName")
.subAggregation(AggregationBuilders.avg("brandNameAvgPrice").field("price"))));
SearchHits<Goods> searchHits = elasticsearchRestTemplate.search(queryBuilder.build(), Goods.class, IndexCoordinates.of("goods"));
// 获取聚合信息
Aggregations aggregations = (Aggregations)searchHits.getAggregations().aggregations();
assert aggregations != null;
ParsedStringTerms categoryNameAgg = aggregations.get("categoryNameAgg");
//获取总记录数
System.out.println("totalHits = " + searchHits.getTotalHits());
//获取值返回
for (Terms.Bucket bucket : categoryNameAgg.getBuckets()) {
// 获取聚合后的分类名称
String categoryName = bucket.getKeyAsString();
// 获取聚合命中的文档数量
long docCount = bucket.getDocCount();
// 获取聚合后的分类的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象
ParsedAvg avgPrice = bucket.getAggregations().get("categoryNameAvgPrice");
System.out.println(categoryName + "======" + avgPrice.getValue() + "======" + docCount);
ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brandNameAgg");
for (Terms.Bucket brandeNameAggBucket : brandNameAgg.getBuckets()) {
// 获取聚合后的品牌名称
String brandName = brandeNameAggBucket.getKeyAsString();
// 获取聚合后的品牌的平均价格,注意返回值不是Aggregation对象,而是指定的ParsedAvg对象
ParsedAvg brandNameAvgPrice = brandeNameAggBucket.getAggregations().get("brandNameAvgPrice");
System.out.println(" " + brandName + "======" + brandNameAvgPrice.getValue());
}
}
}
}