在社交网站开发外国客户,免费行情软件网站mnw,中山网站设计外包,找项目网文章目录 1. DSL查询文档1.1 DSL查询分类1.2 全文检索查询1.3 精确查询1.4 地理查询1.5 查询算分1.6 布尔查询1.7 结果排序1.8 分页查询1.9 高亮显示 2. RestClient查询文档2.1 查询全部2.2 其他查询语句2.3 排序和分页2.4 高亮显示 1. DSL查询文档
1.1 DSL查询分类
查询所有… 文章目录 1. DSL查询文档1.1 DSL查询分类1.2 全文检索查询1.3 精确查询1.4 地理查询1.5 查询算分1.6 布尔查询1.7 结果排序1.8 分页查询1.9 高亮显示 2. RestClient查询文档2.1 查询全部2.2 其他查询语句2.3 排序和分页2.4 高亮显示 1. DSL查询文档
1.1 DSL查询分类
查询所有查询出所有数据一般测试用。例如match_all全文检索查询利用分词器对用户输入内容分词然后去倒排索引库中匹配。例如 match_querymulti_match_query 精确查询根据精确词条值查找数据一般是查找keyword、数值、日期、boolean等类型字段。例如 idsrangeterm 地理查询根据经纬度查询。例如 geo_distancegeo_bounding_box 复合查询复合查询可以将上述各种查询条件组合起来合并查询条件。例如 boolfunction_score
下面我们以一个基本的查询语句来举例比如我们需要查询索引库 hotel 全部内容使用的DSL语句如下
GET /hotel/_search
{query: {match_all: {}}
}1.2 全文检索查询
全文检索常用的有两个查询函数分别是 match 以及 multi_match 。
match 函数会对用户输入内容分词然后去倒排索引库检索语法如下GET /indexName/_search
{query: {match: {FIELD: TEXT}}
}比如搜索 hotel 索引库中的 name 字段如下GET /hotel/_search
{query: {match: {name: 酒店}}
}multi_match 函数与 match 类似不过允许查询多个字段语法如下GET /indexName/_search
{query: {multi_match: {query: TEXT,fields: [FIELD1, FIELD2]}}
}比如搜索 hotel 索引库中的 name 字段如下GET /hotel/_search
{query: {multi_match: {query: 如家,fields: [name, brand]}}
}1.3 精确查询
精确查询的语句函数主要有 term 语句和 range 语句精确查询必须要查询的内容与字段里面的所有内容完全匹配才行一般的查询是keyword、数值、日期、boolean等类型字段。
term 的语法如下GET /indexName/_search
{query: {term: {FIELD: {value: VALUE}}}
}range 查询的语法如下GET /indexName/_search
{query: {range: {FIELD: {gte: 10,lte: 20}}}
}其中 gt 是大于lt 是小于gte 是大于等于lte 是小于等于。
1.4 地理查询
地理查询主要是根据经纬度来进行查询的主要使用的函数有 geo_bounding_box 和 geo_distance 。
geo_bounding_box 函数的语法如下GET /indexName/_search
{query: {geo_bounding_box: {FIELD: {top_left: {lat: 31.1,lon: 121.5},bottom_right: {lat: 30.9,lon: 121.7}}}}
}该函数能够将在一个矩阵框中的经纬度全部筛选出来该矩阵的左上角的点以及右下角的点如上述定义所示根据这两个点已经就能够定义一个矩形了。geo_distance 函数的语法如下GET /indexName/_search
{query: {geo_distance: {distance: 15km,FIELD: 31.21,121.5}}
}该函数是筛选距离定义经纬度点指定距离内的所有点这个距离指的是距定义点方圆的距离。
1.5 查询算分
在使用关键词等进行查询的时候会有一个 _score 属性这就是每条数据与查询关键词的相关性分数该分数在ElasticSearch5.0之前是使用的 TF-IDF 算法进行的评分ElasticSearch5.0之后是使用的 BM25 算法进行评分。 我们可以使用 function score query修改文档的相关性算分query score根据新得到的算分排序。修改算分的示例语句如下
GET /hotel/_search
{query: {function_score: {query: { match: {all: 外滩} },functions: [{filter: {term: {id: 1}},weight: 10}],boost_mode: multiply}}
}在上面的例句中
query 是正常的查询语句filter 表示过滤条件符合条件的文档才会被重新算分weight 是指算分函数算分函数的结果称为 function score 将来会与原始的 query score 运算得到新算分常见的算分函数有 weight给一个常量值作为函数结果function scorefield_value_factor用文档中的某个字段值作为函数结果random_score随机生成一个值作为函数结果script_score自定义计算公式公式结果作为函数结果 boost_mode 定义function score与query score的运算方式常见的加权方式如下 multiply两者相乘。默认就是这个replace用function score 替换 query score其它sum、avg、max、min
1.6 布尔查询
布尔查询时一个或多个查询的字句子查询的组合方式有
must必须匹配每个子查询类似“与”should选择性匹配子查询类似“或”must_not必须不匹配不参与算分类似“非”filter必须匹配不参与算分
示例如下
GET /hotel/_search
{query: {bool: {must: [{term: {city: 上海 }}],should: [{term: {brand: 皇冠假日 }},{term: {brand: 华美达 }}],must_not: [{ range: { price: { lte: 500 } }}],filter: [{ range: {score: { gte: 45 } }}]}}
}1.7 结果排序
elasticsearch支持对搜索结果排序默认是根据相关度算分_score来排序。可以排序字段类型有keyword类型、数值类型、地理坐标类型、日期类型等。
GET /indexName/_search
{query: {match_all: {}},sort: [{FIELD: desc // 排序字段和排序方式ASC、DESC}]
}以上就是指定字段的排序 ASC 代表升序DASC 代表降序如果有多个排序字段那么按照从上到下的优先级进行排序。
举个例子如果我们想要按照某一个经纬度的距离进行排序那么模板如下
GET /indexName/_search
{query: {match_all: {}},sort: [{_geo_distance : {FIELD : 纬度经度,order : asc,unit : km}}]
}1.8 分页查询
ElasticSearch查询时默认只显示10条数据那如果我们想要看到其他的数据怎么办呢这就涉及到了分页。ElasticSearch分页的方式有很多种这里讲一下使用 from, size 参数以及 search after 来进行分页。 使用 from, size 两个参数进行分页。可以在搜索时规定这两个参数的值 from 表示从何处开始进行查看默认是 0 0 0 size 表示每次查询的信息有多少条。比如每也10条数据我们想要查看第二页的数据那么就需要设置 from: 10,size:10 格式如下 GET /hotel/_search
{query: {match_all: {}},from: 990, // 分页开始的位置默认为0size: 10, // 期望获取的文档总数sort: [{price: asc}]
}但是这种方式要求 fromsize 不大于 10000 10000 10000 且该方式是先查询所有的数据然后再对数据进行截取不可避免的该方式会面临深度分页问题即我们的ElasticSearch肯定是要有集群的当我们需要取出前 1000 1000 1000 个结果时需要整理每个集群中的结果再重新排序再选出前 1000 1000 1000 个但是如果结果集很大这对内存以及CPU的消耗就很大。 使用 search after 进行分页。针对深度分页ElasticSearch提供了 search after 方法该方法没有查询上限只限制了单次的 size 不超过 10000 10000 10000 。 search after 方法分页时需要排序原理是从上一次的排序值开始查询下一页数据。 例如我们查询到了第一页的数据最后一条数据如下 我们将最后一条数据的 sort 字段复制到 search_after 中再规定一个 size 属性就能够在该条数据之后再显示 size 条数据语法模板如下 GET /hotel/_search
{query: {match_all: {}},search_after: [161],size: 10,sort: [{price: asc}]
}1.9 高亮显示
在使用搜索引擎进行搜索时我们发现我们输入的关键词显示都是用了高亮进行显示这就是搜索结果的高亮。其实这种高亮的显示是在搜索结果中将关键字用标签进行标注出来再到页面中进行CSS的渲染。默认在进行高亮查询时会在高亮字段前后添加 em 标签如果想添加其他标签可以进行更改语法模板如下
GET /hotel/_search
{query: {match: {FIELD: TEXT}},highlight: {fields: { // 指定要高亮的字段,可以添加多个字段FIELD: {pre_tags: em, // 用来标记高亮字段的前置标签默认就是em标签所以可以不写post_tags: /em // 用来标记高亮字段的后置标签}}}
}这里我们对酒店数据进行查询的例子如下
GET /hotel/_search
{query: {match: {all: 如家}},highlight: {fields: { name: {require_field_match: false}}}
}在上面的搜索中 all 字段是 name, brand 等字段 copy_to 后的属性而下面高亮显示的属性是 name 属性这就导致了查询的属性与高亮显示的属性不一致的情况这种情况默认是不会进行高亮显示的需要查询的属性与高亮显示的属性一致才进行高亮显示。但是我们就可以设置 require_field_match 属性为 false 控制高亮显示与查询字段和高亮显示的字段无关。
高亮结果显示如下
2. RestClient查询文档
2.1 查询全部
查询全部的代码如下所示 Testvoid testMatchAll() throws IOException {//1.准备Request对象SearchRequest request new SearchRequest(hotel);//2.准备DSLrequest.source().query(QueryBuilders.matchAllQuery());//3.发送请求SearchResponse response restHighLevelClient.search(request, RequestOptions.DEFAULT);//4.解析响应SearchHits searchHits response.getHits();//5.1 获取总条数long total searchHits.getTotalHits().value;System.out.println(共有 total 条数据);//5.2 文档数组存储文档SearchHit[] hits searchHits.getHits();for(SearchHit hit: hits){//6.获取文档sourceString json hit.getSourceAsString();//7.反序列化HotelDoc hotelDoc JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);}System.out.println(response);}其中每一段代码与DSL语句的对应关系如下
2.2 其他查询语句
其实其他查询语句与上述查询全部的语句中大部分代码是类似的唯一变化的是 request.source().query() 中 query 的参数。
match// 分别是字段名和查询的语句
request.source().query(QueryBuilders.matchQuery(all, 如家));multi_match// 分别是查询词以及查询字段
request.source().query(QueryBuilders.matchQuery(如家, name, brand));term// 分别是查询字段以及查询词
request.source().query(QueryBuilders.termQuery(city, 成都));range// 分别是查询词以及查询条件
request.source().query(QueryBuilders.rangeQuery(price).gte(100).lte(300));布尔查询// 构建布尔查询
BoolQueryBuilder boolQuery QueryBuilders.boolQuery();
// must语句
boolQuery.must(QueryBuilders.termQuery(city, 成都));
//filter语句
boolQuery.filter(QueryBuilders.rangeQuery(price).gte(100).lte(300))
request.source().query(boolQuery);2.3 排序和分页
排序与分页的代码也仅需要在 request.source().query() 上进行修改即可修改示例如下
request.source().query(QueryBuilders.termQuery(city, 成都));
// 排序
request.source().sort(price, SortOrder.ASC);
//分页
request.source().from(0).size(10);2.4 高亮显示
高亮显示仅需要在查询的内容后面添加一行代码即可如下
// 设置高亮显示并关闭查询字段与高亮字段一致
request.source().highlighter(new HighlightBuilder().field(name).requireFieldMatch(false));但是设置了高亮后输出发现并不是高亮的内容需要高亮的内容前后没有标签这是怎么回事呢
回顾上面可以发现高亮的内容与 _source 内容是分开的是重新的一个字段于是我们需要用高亮的字段覆盖原来的字段那么循环里面的代码如下
for(SearchHit hit: hits){//6.获取文档sourceString json hit.getSourceAsString();//7.反序列化HotelDoc hotelDoc JSON.parseObject(json, HotelDoc.class);//获取高亮结果MapString, HighlightField highlightFieldMap hit.getHighlightFields();//简洁判断判断highlightFieldMap是否为空或者size0if(!CollectionUtils.isEmpty(highlightFieldMap)){//获取highlight属性中的name属性HighlightField highlightField highlightFieldMap.get(name);if(highlightField ! null){//得到name属性的第一个值的字符串String name highlightField.getFragments()[0].string();//覆盖原本的值hotelDoc.setName(name);}}System.out.println(hotelDoc);
}