成都网站建设 川icp备,字体在线设计网站,阳新县建设局网站,青岛信息推广网站一、DSL查询文档
1.DSL查询分类
①查询所有#xff1a;match_all
②全文检索#xff1a;利用分词器对用户输入的内容分词#xff0c;倒排索引去匹配 match_query multi_match_query
③精确查询#xff1a;根据精确词条查找数据#xff0c;查找的是keyword,数值,日期,b…一、DSL查询文档
1.DSL查询分类
①查询所有match_all
②全文检索利用分词器对用户输入的内容分词倒排索引去匹配 match_query multi_match_query
③精确查询根据精确词条查找数据查找的是keyword,数值,日期,boolean类型字段 ids,range,term
④地理geo查询根据经纬度查询 geo_distance geo_bounding_box
⑤复合查询将各种条件组合起来合并查询条件 bool function_score 总结查询DSL的基本语法是什么
GET /索引库名/_search
{ query: { 查询类型: { FIELD: TEXT}}}
2.全文检索
全文检索查询会对用户输入内容进行分词。用于搜索框搜索 ①match查询对用户输入的内容分词然后倒排索引库查询。一个字段 查询三钻的酒店
GET /hotel/_search
{query: {match: {starName: 三钻}}
}②multi_match多个字段查询。参与的字段越多查询性能越差。 查询品牌酒店名商业圈有“外滩如家”
GET /hotel/_search
{query: {multi_match: {query: 外滩如家,fields: [brand,name,business]}}
}3.精确查询
查询的keyword不进行分词的字段
①term:根据词条准确值查询
②range:范围查询(价格) ①term: 查询品牌是“7天酒店”
GET /hotel/_search
{query: {term: {brand: {value: 7天酒店}}}
}②range:
查询200-250酒店 GET /hotel/_search
{query: {range: {price: {gte: 200,lte: 250}}}
}总结精确查询常见的有哪些
term查询根据词条精确匹配一般搜索keyword类型、数值类型、布尔类型、日期类型字段range查询根据数值范围查询可以是数值、日期的范围
4.地理查询
场景
查询附近的酒店附近的人打车附近的出租车 ①矩形范围内geo_bounding_box ②以指定中心点为半径 查询这个点15公里范围内的酒店
GET /hotel/_search
{query: {geo_distance:{distance:15km,location:31.282444,121.479385}}
}5.相关性算分竞价排名
①fuction score:算分函数查询可以控制文档相关性算分控制文档排名 ②词条频率越高得分越高排名越靠前 ③elasticsearch中的相关性打分算法是什么
TF-IDF在elasticsearch5.0之前会随着词频增加而越来越大BM25在elasticsearch5.0之后会随着词频增加而增大但增长曲线会趋于水平 6.修改相关性算分竞价排名
使用 function score query可以修改文档的相关性算分query score根据新得到的算分排序。 ①原始条件查询搜索文档并根据相关性打分(query score)
②过滤条件符合条件的文档才重新算分
③算分函数
算分函数算分函数的结果称为function score 将来会与query score运算得到新算分常见的算分函数有
weight给一个常量值作为函数结果function scorefield_value_factor用文档中的某个字段值作为函数结果random_score随机生成一个值作为函数结果script_score自定义计算公式公式结果作为函数结果
④加权模式定义function score与query score的运算方式包括
multiply两者相乘。默认就是这个replace用function score 替换 query score其它sum、avg、max、min
案例搜索外滩的酒店“如家”品牌给公司充钱了让他的排名靠前一些。
分析:
①文档为品牌是“如家”的
②算分函数是weight
③加权模式是求和sum
GET /hotel/_search
{query: {function_score: {query: {match: {all: 外滩}},functions: [{filter: {term: {brand: 如家}},weight: 2}],boost_mode: sum}}
}7.复合查询Boolean Query
布尔查询是一个或多个查询子句的组合。子句组合方式
must:”与”必须匹配每个子查询
should:“或”选择性匹配子查询
must_not必须不匹配不参与算分类似“非”
filter必须匹配不算分。
案例1查询上海的酒店品牌是皇冠假日或华美达。价格不低于500评分是大于45分的 案例2搜索名字包含“如家”价格不高于400在坐标31.21,121.5周围10km范围内的酒店。
GET /hotel/_search
{query: {bool: {must: [{match: {name: 如家}}],must_not: [{range: {price: {gte: 400}}}],filter: [{geo_distance: {distance: 10km,location: {lat: 31.21,lon: 121.5}}}]}}
}二、搜索结果处理
1.排序
es支持对搜索结果排序默认是根据相关度算分(_score)排序。可以排序的字段keyword类型数值类型地理坐标类型日期类型。
排序语法 地理坐标排序语法 案例1对酒店数据按照用户评价降序排序评价相同的按照价格升序排序
GET /hotel/_search
{query: {match_all: {}},sort: [{score:desc},{price: asc}]
}案例2实现对酒店数据按照到你的位置坐标的距离升序排序
获取经纬度的方式https://lbs.amap.com/demo/jsapi-v2/example/map/click-to-get-lnglat/
GET /hotel/_search
{query: {match_all: {}},sort: [{_geo_distance: {location: {lat: 31.220393,lon: 121.544427},order: asc,unit: km}}]
}2.分页
es的搜索结果默认是top10条。
es通过修改fromsize参数控制返回的分页结果 深度分页问题
ES是分布式的所以会面临深度分页问题。例如按price排序后获取from 990size 10的数据 ①首先在每个数据分片上都排序并查询前1000条文档。
②然后将所有节点的结果聚合在内存中重新排序选出前1000条文档
③最后从这1000条中选取从990开始的10条文档
如果搜索页数过深或者结果集from size越大对内存和CPU的消耗也越高。因此ES设定结果集查询的上限是10000
总结
from size
优点支持随机翻页缺点深度分页问题默认查询上限from size是10000场景百度、京东、谷歌、淘宝这样的随机翻页搜索
after search
优点没有查询上限单次查询的size不超过10000缺点只能向后逐页查询不支持随机翻页场景没有随机翻页需求的搜索例如手机向下滚动翻页
3.高亮
搜索关键字突出显示。 原理
①搜索关键字标记出来
②页面加css样式 案例如家酒店高亮 三、RestClient查询文档
1.快速入门
①请求DSL的组织 RestAPI中其中构建DSL是通过HighLevelRestClient中的resource()来实现的其中包含了查询、排序、分页、高亮等所有功能 RestAPI中其中构建查询条件的核心部分是由一个名为QueryBuilders的工具类提供的其中包含了各种查询方法 ②解析结果response ③查询全部酒店的完整代码 Test
void testMatchAll() throws IOException {// 1.准备查询请求,参数是索引库名SearchRequest request new SearchRequest(hotel);// 2.组织DSL参数request.source().query(QueryBuilders.matchAllQuery());// 3.发送请求得到响应SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4.解析结果SearchHits searchHits response.getHits();// 4.1 获取查询的条数long total searchHits.getTotalHits().value;// 4.2 获取查询的集合SearchHit[] hits searchHits.getHits();// 4.3 遍历ListHotelDochotelDocList new ArrayList();for (SearchHit hit : hits) {// 转换为JsonString json hit.getSourceAsString();// 转换为java对象HotelDoc hotelDoc JSONObject.parseObject(json, HotelDoc.class);// 保存在集合中hotelDocList.add(hotelDoc);}System.out.println(hotelDocList);
}查询的基本步骤是
创建SearchRequest对象准备Request.source()也就是DSL。 QueryBuilders来构建查询条件传入Request.source() 的 query() 方法发送请求得到结果解析结果参考JSON结果从外到内逐层解析
2.构建查询条件只要记住一个类QueryBuilders
①全文检索查询(分词模糊查询)
单字段QueryBuilders.matchQuery(字段名值)
多字段QueryBuilders.multiMatchQuery(值, 字段1,字段2);
演示酒店名字带有“如家“的有哪些 request.source().query(QueryBuilders.termQuery(name,如家));
②精确查询不分词
精确查询常见的有term查询和range查询 ③复合查询boolean query
查询品牌为如家价格在200元内的酒店
// 创建bool查询
BoolQueryBuilder boolQuery QueryBuilders.boolQuery();
// 添加must条件
boolQuery.must(QueryBuilders.termQuery(brand,如家));
// 添加filter条件
boolQuery.filter(QueryBuilders.rangeQuery(price).lte(200));
request.source().query(boolQuery);3.分页和排序 演示查询名为“如家“的酒店查询结果进行价格降序每页显示3条
// 页码
int page 1,size3;
// 2.组织DSL
// 2.1 查询
request.source().query(QueryBuilders.termQuery(name,如家));
// 2.2 分页 从from序号数size个
request.source().from((page-1)*size).size(size);
// 2.3 价格排序
request.source().sort(price, SortOrder.DESC);4.高亮
根据name搜索高亮 代码
Test
void testHight() throws IOException{// 1.请求requestSearchRequest request new SearchRequest(hotel);// 2. 组织DSLrequest.source().query(QueryBuilders.matchQuery(all,如家));request.source().highlighter(new HighlightBuilder().field(name).requireFieldMatch(false));// 3.发送请求得到响应SearchResponse response client.search(request, RequestOptions.DEFAULT);// 4.分析结果SearchHits searchHits response.getHits();// 5.解析SearchHit[] hitss searchHits.getHits();// 6.遍历for (SearchHit hit : hitss) {// 转换为jsonString json hit.getSourceAsString();// 得到对象HotelDoc hotelDoc JSONObject.parseObject(json, HotelDoc.class);// 获取高亮结果MapString, HighlightField highlightFields hit.getHighlightFields();// 根据字段获取HighlightField highlightField highlightFields.get(name);// 获取高亮值String name highlightField.getFragments()[0].string();// 覆盖结果hotelDoc.setName(name);System.out.println(name);}}四、黑马旅游案例
Overridepublic PageResult search(RequestParams params) throws IOException {// 1.得到请求参数String key params.getKey();Integer page params.getPage();Integer size params.getSize();String sortBy params.getSortBy();String brand params.getBrand();String starName params.getStarName();String city params.getCity();Integer minPrice params.getMinPrice();Integer maxPrice params.getMaxPrice();String location params.getLocation();// 2.创建搜索请求SearchRequest request new SearchRequest(HotelConstants.HOTEL_INDEX);// 3.编写DSL 组合查询boolQueryBoolQueryBuilder boolQuery QueryBuilders.boolQuery();// 3.1.1 输入框关键字mustif (key ! null !.equals(key)) { //输入框不为空模糊查询boolQuery.must(QueryBuilders.matchQuery(all, key));} else {//输入框为空查询全部boolQuery.must(QueryBuilders.matchAllQuery());}// 3.1.2 城市--filterif (city ! null !.equals(city)) {boolQuery.filter(QueryBuilders.termQuery(city, city));}// 3.1.3 品牌--filterif (brand ! null !.equals(brand)) {boolQuery.filter(QueryBuilders.termQuery(brand, brand));}// 3.1.4 星级--filterif (starName ! null !.equals(starName)) {boolQuery.filter(QueryBuilders.termQuery(starName, starName));}// 3.1.5 价格--filterif (minPrice ! null maxPrice ! null) {boolQuery.filter(QueryBuilders.rangeQuery(price).gte(minPrice).lte(maxPrice));}// 3.1.6 查询条件// 3.1.7 广告推荐算分查询(查询条件算分条件)FunctionScoreQueryBuilder functionScoreQuery QueryBuilders.functionScoreQuery(boolQuery,new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery(isAD,true),// 算分条件ScoreFunctionBuilders.weightFactorFunction(10) // 算分比例)});request.source().query(functionScoreQuery);// 3.2 页码request.source().from((page - 1) * size).size(size);// 3.3 排序if (location ! null !.equals(location)) {request.source().sort(SortBuilders.geoDistanceSort(location, new GeoPoint(location)).order(SortOrder.ASC).unit(DistanceUnit.KILOMETERS));}if (!SortConstants.DEFAULT.equals(sortBy)) {request.source().sort(sortBy, SortOrder.DESC);}//4. 发送请求得到响应SearchResponse response client.search(request, RequestOptions.DEFAULT);// 5.解析响应PageResult pageResult handleResponse(response);return pageResult;}