赞
踩
目录
ElasticSearch是一个开源的、支持分布式的、能够进行近实时搜索和分析、能够处理PB级数据量的搜索引擎。目前有很多平台和工作场景会涉及到对ElasticSearch的使用。
Mysql数据操作具备事务性,而ElasticSearch没有
MySQL支持外键,而ElasticSearch不支持
Mysql采用B+树索引,而ElasticSearch采用倒排索引
ES在使用时,会涉及到五大核心概念:索引(Index)、映射(Mapping)、域(Field)、文档(Documen)、倒排索引。以一张MySQL中数据表为例:
ElasticSearch | Mysql |
---|---|
索引(Index) | 表(Table) |
映射(Mapping) | 表结构 |
域(Field) | 字段列(Column) |
文档(Document) | 一条数据(Row) |
索引相当于关系型数据库中的一张表,一个index中包含若干个document,通过index代替一类类似的或相同的document。
# PUT 索引名称
PUT person
#查询单个索引 GET 索引名称
GET person
# 查询多个索引信息 GET 索引名称,索引名称
PUT person1
GET person,person1
# 查询所有索引信息
GET _all
#删除索引 DELETE 索引名称
DELETE person1
域(Field)相当于数据表中的字段列,当有了索引之后,需要在索引中设置域的相关信息如:名称,类型等。这个过程称为:映射(Mapping)。相当于关系型数据库中设置表的信息。
字符串
text:会进行分词,如小米手机,会分成:小米,手机。 被分出来的每一个词,称为term(词条)
keyword:不会进行分词,如小米手机,只有一个词条,即小米手机。
数值
long:带符号64位整数
integer:带符号32位整数
short:带符号16位整数
byte:带符号8位整数
double:双精度64位浮点数
float:单精度32位浮点数
half_float:半精度16位浮点数
布尔:
boolean
二进制:
binary
日期:
date
范围类型:
integer_range
float_range
long_range
double_range
date_range
数组
对象
(1)为已存在的索引库添加映射
PUT person/_mapping
{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
}
}
}
#查看索引映射信息
GET person/_mapping
(2)创建索引并添加映射
#创建索引并添加映射
PUT person
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "integer"
}
}
}
}
(3)添加字段
对于映射,只能进行字段添加,不能对字段进行修改或删除,如有需要,则重新创建映射。
#添加字段
PUT person/_mapping
{
"properties":{
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"address":{
"type":"text"
}
}
}
ES中最小的数据单元,代表索引中的一条数据,通常是使用json的数据格式表示的
(1)添加文档,手动设置id
#添加文档,手动设置id
POST person/_doc/1
{
"name":"朱吴",
"age":"23",
"address":"南昌"
}
(2)添加文档,自动生成id
#添加文档,自动生成id
POST person/_doc
{
"name":"朱徐",
"age":"25",
"address":"深圳"
}
(1)根据id查询文档
#GET 索引名称/_doc/文档id
GET person/_doc/1
(2)查询所有文档
#GET 索引名称/_search
GET person/_search
PUT person/_doc/1
{
"name":"朱武",
"age":"26",
"address":"深圳"
}
#DELETE 索引名称/_doc/文档id
DELETE person/_doc/1
要想理解倒排索引,首先思考一个问题,获取某个文件夹下所有文件名中包含Spring的文件
1)确定要搜索的文件夹 2)遍历文件夹下所有文件 3)判断文件名中是否包含Spring
这种思维可以理解为是一种正向思维的方式,从外往内,根据key找value。这种方式可以理解为正向索引。
而ElasticSearch为了提升查询效率,采用反向思维方式,根据value找key。
索引及映射准备
PUT hotel
{
"mappings": {
"properties": {
"name":{
"type": "text",
"analyzer": "ik_max_word"
},
"address":{
"type": "text",
"analyzer": "ik_max_word"
},
"brand":{
"type": "keyword"
},
"type":{
"type": "keyword"
},
"price":{
"type": "integer"
},
"specs":{
"type": "keyword"
},
"salesVolume":{
"type": "integer"
},
"area":{
"type": "text",
"analyzer": "ik_max_word"
},
"imageUrl":{
"type": "text"
},
"synopsis":{
"type": "text",
"analyzer": "ik_max_word"
},
"createTime":{
"type": "date",
"format": "yyyy-MM-dd"
},
"isAd":{
"type":"integer"
}
}
}
}
在ES中提供了批量操作的方式:例如
#新增一号用户
#删除一号用户
#新增二号用户
POST _bulk
{"create":{"_index":"user","_id":"1"}}
{"name":"张三","age":18,"address":"北京"}
{"delete":{"_index":"user","_id":"1"}}
{"create":{"_index":"user","_id":"2"}}
{"name":"李四","age":20,"address":"黑龙江"}
在代码中,批量导入时,从MySQL中查出所有数据后批量导入ES
- //批量导入
- @Override
- public int addDocToES() {
-
- //todo 批量导入文档实现
-
- // 1.创建批量导入对象
- BulkRequest bulkRequest = new BulkRequest();
- //2.从MySQL数据库中查出所有数据
- List<HotelEntity> hotelList = hotelMapper.selectList(null);
-
- //3.遍历,使用带有转换日期的JSON序列化并将数据加入到创建的导入对象中
- for (HotelEntity hotelEntity : hotelList) {
- //3.1将实体进行序列化
- String data = JSON.toJSONStringWithDateFormat(hotelEntity, "yyyy-MM-dd", SerializerFeature.WriteDateUseDateFormat);
- //3.2 实例化IndexRequest并设置索引名,文档内容(对象的JSON格式)
- IndexRequest indexRequest = new IndexRequest("hotel").source(data, XContentType.JSON);
- //3.3加入批量批量导入对象中
- bulkRequest.add(indexRequest);
- }
-
- try {
- //4.通过restHighLevelClient调用bulk方法,开启执行批量操作
- BulkResponse responses = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
- return responses.status().getStatus();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return 0;
- }
GET hotel/_search
{
"query": {
"match_all": {}
}
}
- //查询全部
- /*
- GET hotel/_search
- {
- "query": {
- "match_all": {}
- }
- }
- */
- @Override
- public Map<String, Object> matchAllQuery() {
-
- //todo 查询全部文档实现
- //1.创建搜索请求对象SearchRequest
- SearchRequest searchRequest = new SearchRequest("hotel");
- //2.创建searchSourceBuilder,进行筛选条件填充
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //2.1构建查询方式
- QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
- searchSourceBuilder.query(queryBuilder);
- searchRequest.source(searchSourceBuilder);
- //3.通过restHighLevelClient调用search方法,开启查询
- try {
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //4.处理查询结果
- //4.1获取查询结果
- SearchHits hits = searchResponse.getHits();
- long totalHits = hits.getTotalHits().value;
- SearchHit[] hits1 = hits.getHits();
- //4.2,反序列化后添加到集合中
- List<HotelEntity>list = new ArrayList<>();
- for (SearchHit searchHit : hits1) {
- String sourceAsString = searchHit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //4.3封装成map
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize",totalHits);
-
- return map;
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
GET hotel/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5
}
- public Map<String, Object> pageQuery(int current, int size) {
- //todo 分页查询文档实现
- //1.创建搜索请求对象SearchRequest
- SearchRequest searchRequest = new SearchRequest("hotel");
- //2.创建SearchSourceBuilder,进行筛选条件填充
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //2.1构建查询方式
- MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
- searchSourceBuilder.query(queryBuilder);
- //2.2设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
- //3.执行查询
- try {
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
- //4.处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long hitsTotal = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit searchHit : hits){
- String sourceAsString = searchHit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- Map<String, Object> map = new HashMap<>();
- map.put("list", list);
- map.put("totalResultSize", hitsTotal);
- map.put("current", current);
- //设置总页数
- map.put("totalPage",(hitsTotal+size-1)/size);
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
termQuery:不会对查询条件进行分词(keyword)
GET hotel/_search
{
"query": {
"term": {
"brand": {
"value": "万豪"
}
}
}
}
GET hotel/_search
{
"query": {
"term": {
"brand": "万豪"
}
}
}
- public Map<String, Object> brandTermQuery(int current, int size, Map<String, Object> searchParam) {
-
- //todo 按品牌精确查询实现
- //1.构建查询请求对象SearchRequest
- SearchRequest searchRequest = new SearchRequest("hotel");
- //2.创建SearchSourceBuilder,进行筛选条件填充
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //2.1构建查询方式
- if(!StringUtils.isEmpty(searchParam.get("brand"))){
- QueryBuilder queryBuilder = QueryBuilders.termQuery("brand", searchParam.get("brand").toString());
- searchSourceBuilder.query(queryBuilder);
- }
- //2.2设置分页
- searchSourceBuilder.from((current - 1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
- //3.执行查询
- try {
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //4.处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long hitsTotal = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString, HotelEntity.class));
- }
- //5.封装返回结果
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize",hitsTotal);
- map.put("current",current);
- //6.设置总页数
- map.put("totalPage",(hitsTotal+size-1)/size);
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
4.2.3分词匹配查询
GET hotel/_search
{
"query": {
"match": {
"name":"北京市东城区万豪酒店"
}
}
}
- public Map<String, Object> nameMatchQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //todo 根据酒店名称匹配查询实现
-
- //1.构建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //2.创建SearchSourceBuilder,进行筛选条件填充
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //3.查询条件构造
- MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", searchParam.get("name"));
- searchSourceBuilder.query(queryBuilder);
- //4.设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
- try {
- //5.执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //6.处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- //6.1命中结果总数
- long hitsTotal = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //6.2.封装返回结果
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize",hitsTotal);
- map.put("current",current);
- //6.3.设置总页数
- map.put("totalPage",(hitsTotal+size-1)/size);
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
wildcardQuery:会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0个或多个字符)
GET hotel/_search
{
"query": {
"wildcard": {
"brand": {
"value": "美*"
}
}
}
}
- public Map<String, Object> nameWildcardQuery(Integer current, Integer size, Map<String, Object> searchParam) {
- //todo 根据酒店名称模糊查询
- //1.构建查询对象searchRequest
- SearchRequest searchRequest = new SearchRequest("hotel");
- //2.构造searchSourceBuilder,构造DSL
- SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
- WildcardQueryBuilder queryBuilder = QueryBuilders.wildcardQuery("brand", searchParam.get("name") + "*");
- sourceBuilder.query(queryBuilder);
- //3.设置分页
- sourceBuilder.from((current-1)*size);
- sourceBuilder.size(size);
- searchRequest.source(sourceBuilder);
- try {
- //4.执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //5.处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long hitsTotal = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //6.封装返回信息
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize", hitsTotal);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (hitsTotal + size - 1) / size);
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
queryStringQuery:
•会对查询条件进行分词。
•然后将分词后的查询条件和词条进行等值匹配
•默认取并集(OR)
•可以指定多个查询字段
GET hotel/_search
{
"query": {
"query_string": {
"fields": ["name","synopsis","area","address"],
"query": "如心 OR spa"
}
}
}
- public Map<String, Object> searchQueryStringQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //构建查询对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //构建searchSourceBuilder,设置DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //根据name,synopsis,area,address进行多域查询
- QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(searchParam.get("condition").toString())
- .field("name")
- .field("synopsis")
- .field("area")
- .field("address")
- .defaultOperator(Operator.OR);
- searchSourceBuilder.query(queryBuilder);
- //设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
-
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //封装返回信息
- Map<String,Object> map = new HashMap<>();
- map.put("list", list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
(1)新建用于存储用户搜索记录的索引库
PUT suggest
{
"mappings": {
"properties": {
"name":{
"type": "completion",
"analyzer": "ik_max_word"
}
}
}
}
(2)数据查询
GET suggest/_search
{
"suggest": {
"my-suggest": {
"prefix": "酒店环境",
"completion": {
"field": "name",
"size":10
}
}
}
}
GET suggest/_search
{
"suggest": {
"my-suggest": {
"prefix": "酒店",
"completion": {
"field": "name",
"size":10
}
}
}
}
- public List<String> searchSuggestInfo(String key) {
-
- //定义结果集
- List<String> result = new ArrayList<>();
- //构建查询对象
- SearchRequest searchRequest = new SearchRequest("suggest");
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //构建自动补全搜索
- SuggestBuilder suggestBuilder = new SuggestBuilder();
- CompletionSuggestionBuilder suggestion= SuggestBuilders.completionSuggestion("name").text(key).size(10);
- suggestBuilder.addSuggestion("my-suggest",suggestion);
- searchSourceBuilder.suggest(suggestBuilder);
- searchRequest.source(searchSourceBuilder);
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理自动补全查询结果
- Suggest suggest = searchResponse.getSuggest();
- CompletionSuggestion completionSuggestion = suggest.getSuggestion("my-suggest");
- List<CompletionSuggestion.Entry> entries = completionSuggestion.getEntries();
-
- Map<String, Object> map = new HashMap<>();
- if (entries!=null && entries.size()>0){
- entries.forEach(entry -> {
- if (!ObjectUtils.isEmpty(entry.getOptions())){
- entry.forEach(action -> {
- String suggestInfo = action.getText().toString();
- if (suggestInfo.equals(key)){
- return;
- }
- result.add(suggestInfo);
- });
- }else {
- map.put("name",key);
- }
- });
- }
- //向索引库增量添加查询条件
- if (!ObjectUtils.isEmpty(map)) {
- IndexRequest indexRequest = new IndexRequest("suggest").source(map);
- restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
- }
- System.out.println("list" + result);
- return result;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
4.2.7排序查询
#降序
GET hotel/_search
{
"sort": [
{
"salesVolume": {
"order": "desc"
}
}
]
}#升序
GET hotel/_search
{
"sort": [
{
"salesVolume": {
"order": "asc"
}
}
]
}
- public Map<String, Object> salesSortQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //构建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //构建SearchSourceBuilder,构建DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- if ("desc".equalsIgnoreCase(searchParam.get("sortWay").toString())){
- searchSourceBuilder.sort("salesVolume", SortOrder.DESC);
- }else {
- searchSourceBuilder.sort("salesVolume",SortOrder.ASC);
- }
- //设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
-
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //map封装
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
- map.put("sortWay",searchParam.get("sortWay"));
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
GET hotel/_search
{
"query": {
"range": {
"price": {
"gte": 500,
"lte": 2000
}
}
}
}
- public Map<String, Object> priceRangeQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //创建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //创建SearchSourceBuilder,设置DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("price")
- .gte(searchParam.get("minPrice"))
- .lte(searchParam.get("maxPrice"));
- searchSourceBuilder.query(queryBuilder);
- //设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity>list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- //map封装
- Map<String,Object> map = new HashMap<>();
- map.put("list",list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
-
- map.put("minPrice", searchParam.get("minPrice"));
- map.put("maxPrice", searchParam.get("maxPrice"));
-
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
boolQuery:对多个查询条件连接。
连接方式:
•must(and):条件必须成立
•must_not(not):条件必须不成立
•should(or):条件可以成立
•filter:条件必须成立,性能比must高。
#must单独使用 品牌必须是万豪,地区必须是北京
GET hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"brand": {
"value": "万豪"
}
}
},
{
"term": {
"area": {
"value": "北京市"
}
}
}
]
}
}
}
# must与filter组合使用 查询品牌为万豪下的,区域为北京,价格范围在500和2000之间的酒店
GET hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"brand": {
"value": "万豪"
}
}
}
],
"filter":[
{
"term": {
"area": "北京市"
}
},
{
"range":{
"price": {
"gte": 500,
"lte": 2000
}
}
}
]
}
}
}
#filter 单独使用 filter可以是单个条件,也可多个条件(数组形式)
GET hotel/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"brand": {
"value": "万豪"
}
}
}
]
}
}
}
- public Map<String, Object> searchBoolQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //创建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //创建 SearchSourceBuilder 对象,设置DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- //多条件查询 :多域、品牌精确、城市精确、星级精确、价格范围、销量排序
- BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
- //多域
- if(!ObjectUtils.isEmpty(searchParam.get("condition"))){
- QueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(searchParam.get("condition").toString())
- .field("name")
- .field("synopsis")
- .field("area")
- .field("address")
- .defaultOperator(Operator.OR);
- boolQueryBuilder.must(queryStringQueryBuilder);
- }
-
- //品牌精准
- if(ObjectUtils.isNotEmpty(searchParam.get("brand"))){
- QueryBuilder termQueryBuilder = QueryBuilders.termQuery("brand", searchParam.get("brand"));
- boolQueryBuilder.filter(termQueryBuilder);
- }
-
- //城市精确
- if (ObjectUtils.isNotEmpty(searchParam.get("area"))) {
- QueryBuilder termQueryBuilder = QueryBuilders.termQuery("area", searchParam.get("area"));
- boolQueryBuilder.filter(termQueryBuilder);
- }
-
- //星级精确
- if (ObjectUtils.isNotEmpty(searchParam.get("specs"))) {
- QueryBuilder termQueryBuilder = QueryBuilders.termQuery("specs", searchParam.get("specs"));
- boolQueryBuilder.filter(termQueryBuilder);
- }
-
- //价格范围
- if(ObjectUtils.isNotEmpty(searchParam.get("minPrice")) && !StringUtils.isEmpty(searchParam.get("maxPrice"))){
- RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price")
- .gte(searchParam.get("minPrice"))
- .lte(searchParam.get("maxPrice"));
- boolQueryBuilder.filter(rangeQueryBuilder);
- }
-
- //销量排序
- if (ObjectUtils.isNotEmpty(searchParam.get("sortWay"))){
- if("desc".equalsIgnoreCase(searchParam.get("sortWay").toString())){
- searchSourceBuilder.sort("salesVolume",SortOrder.DESC);
- }else {
- searchSourceBuilder.sort("salesVolume",SortOrder.ASC);
- }
- }
-
- searchSourceBuilder.query(boolQueryBuilder);
- //设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
-
- searchRequest.source(searchSourceBuilder);
-
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- Map<String, Object> map = new HashMap<>();
- map.put("list", list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
-
- map.put("brand", searchParam.get("brand"));
- map.put("area", searchParam.get("area"));
- map.put("specs", searchParam.get("specs"));
- map.put("sortWay", searchParam.get("sortWay"));
- map.put("minPrice", searchParam.get("minPrice"));
- map.put("maxPrice", searchParam.get("maxPrice"));
-
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
fuzzyQuery
自动纠错查询,会自动尝试将搜索条件进行纠错,然后去跟term进行匹配。
fuzziness:查询允许的最大编辑距离,默认为0
prefix_length:设置前几个字符不允许编辑
GET hotel/_search
{
"query": {
"fuzzy": {
"area": {
"value": "北经市",
"fuzziness": 1,
"prefix_length": 1
}
}
}
}
如需将搜索条件以高亮形式展示,则需要在查询时,设置需要对哪一个域进行高亮展示
fields:指定要对哪个域高亮显示
pre_tags:设置高亮样式前缀
post_tags:设置高亮样式后缀
GET hotel/_search
{
"query": {
"term": {
"name": {
"value": "北京市"
}
}
},
"highlight": {
"fields": {
"name": {
"pre_tags": "<font color = 'red'>",
"post_tags": "</font>"
}
}
}
}
- public Map<String, Object> searchHighLight(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //创建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //创建SearchSourceBuilder对象,设置查询条件DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
- if (ObjectUtils.isNotEmpty(searchParam.get("condition"))){
- QueryBuilder queryBuilder = QueryBuilders.termQuery("name", searchParam.get("condition"));
- searchSourceBuilder.query(queryBuilder);
- }
- //设置分页
- searchSourceBuilder.from((current - 1) * size);
- searchSourceBuilder.size(size);
- //设置高亮显示
- HighlightBuilder highlightBuilder = new HighlightBuilder();
- highlightBuilder.field("name");
- highlightBuilder.preTags("<font color = 'red'>");
- highlightBuilder.postTags("</font>");
-
- searchSourceBuilder.highlighter(highlightBuilder);
- searchRequest.source(searchSourceBuilder);
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- //处理查询结果
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits){
- String sourceAsString = hit.getSourceAsString();
- HotelEntity hotelEntity = JSON.parseObject(sourceAsString, HotelEntity.class);
- //处理高亮结果
- Map<String, HighlightField> highlightFields = hit.getHighlightFields();
- HighlightField highlightField = highlightFields.get("name");
- if (highlightField!=null){
- Text[] fragments = highlightField.getFragments();
- hotelEntity.setName(fragments[0].toString());
- }
- list.add(hotelEntity);
- }
- Map<String, Object> map = new HashMap<>();
- map.put("list", list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
-
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
权重设置的两种方式:索引设置,查询设置
索引设置:不常用,因为随着业务的改变,要设置权重的域也会发生改变,而索引一旦创建则无法修改,除非删除索引重建。
索引设置:
PUT hotel
{
"mappings": {
"properties": {
"name":{
"type": "text",
"analyzer": "ik_max_word",
"boost": 5
},
"address":{
"type": "text",
"analyzer": "ik_max_word",
"boost": 3
}
}
}
}
查询设置:
该方式在开发中很常用,根据业务条件需求,在查询时灵活的配置权重。
在下列查询中,query中的内容为主查询条件,functions中为判断要为哪些数据加权。weight为加权值。
GET hotel/_search
{
"query": {
"function_score": {
"query": {
"query_string": {
"fields": ["name","synopsis","area","address"],
"query": "北京市万豪spa三星"
}
},
"functions": [
{
"filter": {
"term": {
"isAd": "1"
}
},
"weight": 100
}
]
}
}
}
- public Map<String, Object> searchScoreQuery(Integer current, Integer size, Map<String, Object> searchParam) {
-
- //创建查询请求对象
- SearchRequest searchRequest = new SearchRequest("hotel");
- //创建SearchSourceBuilder,设置DSL
- SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
-
- QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(searchParam.get("condition").toString())
- .field("name")
- .field("synopsis")
- .field("area")
- .field("address")
- .defaultOperator(Operator.OR);
-
- //构建加权条件
-
- FunctionScoreQueryBuilder.FilterFunctionBuilder[] scoreFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
- new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("isAd", 1), ScoreFunctionBuilders.weightFactorFunction(100))
- };
- FunctionScoreQueryBuilder queryBuilder = QueryBuilders.functionScoreQuery(queryStringQueryBuilder, scoreFunctionBuilders);
- searchSourceBuilder.query(queryBuilder);
- //设置分页
- searchSourceBuilder.from((current-1)*size);
- searchSourceBuilder.size(size);
- searchRequest.source(searchSourceBuilder);
-
- try {
- //执行查询
- SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
- SearchHits searchHits = searchResponse.getHits();
- long totalHits = searchHits.getTotalHits().value;
- SearchHit[] hits = searchHits.getHits();
- List<HotelEntity> list = new ArrayList<>();
- for (SearchHit hit : hits) {
- String sourceAsString = hit.getSourceAsString();
- list.add(JSON.parseObject(sourceAsString,HotelEntity.class));
- }
- Map<String, Object> map = new HashMap<>();
- map.put("list", list);
- map.put("totalResultSize", totalHits);
- map.put("current", current);
- //设置总页数
- map.put("totalPage", (totalHits + size - 1) / size);
-
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。