目录
DSL(Domain SpecificLanguage)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求。
DSL比URI搜索方式功能强大,建议使用DSL方式来完成搜索。
1.查询所有文档
1.1 postman中测试
post http://localhost:9200/wang-003/_search
"query": {
"match_all": {}
}
}
结果说明:
took:本次操作花费的时间,单位为毫秒。
timed_out:请求是否超时
_shards:说明本次操作共搜索了哪些分片
hits:搜索命中的记录
hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前N个文档
hits.max_score:文档匹配得分,这里为最高分
_score:每个文档都有一个匹配度得分,按照降序排列。
_source:显示了文档的原始内容。
1.2 java代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class DSLTest {
@Autowired
RestHighLevelClient highLevelClient;
@Test
public void testSearch() throws IOException {
//声明搜索请求客户端
SearchRequest searchRequest = new SearchRequest("wang-003");
//设置请求类型
searchRequest.types("doc");
//构建搜索源对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//告诉搜索源对象,执行搜索时按照什么类型
//MatchAllQuery===>查询全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//将搜索源对象设置到搜索请求客户端中
searchRequest.source(searchSourceBuilder);
//使用高版本的客户端进行搜索
SearchResponse search = highLevelClient.search(searchRequest);
//获取到 返回值,进行解析
SearchHits hits = search.getHits();
//从hits对象中获取到hits数组
SearchHit[] hits1 = hits.getHits();
//查询出的总条数
long totalHits = hits.getTotalHits();
System.out.println("当前查询出的总数为:"+totalHits);
//循环获取数据
for(SearchHit hit:hits1){
String id = hit.getId();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
}
}
}
2.分页查询
2.1 postman中测试
post http://localhost:9200/wang-003/_search
{
"from":0,"size":2,
"query": {
"match_all": {}
}
}
2.2 java代码
int page = 2;//页码
int size = 2;//每页显示个数
int from = (page - 1) * size;//起记录下标
//MatchAllQuery===>查询全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//设置分页
//当前页码
int page = 2;//页码
int size = 2;//每页显示个数
int from = (page - 1) * size;//起记录下标
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//将搜索源对象设置到搜索请求客户端中
searchRequest.source(searchSourceBuilder);
3.Term Query
Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。
3.1 postman中测试
post http://localhost:9200/wang-003/_search
{
"query": {
"term" : {
"name": "世"
}
}
}
3.2 java代码
//MatchAllQuery===>查询全部
//searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//termQuery====>精确查询,不会对关键字分词
searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));
//设置分页
4.根据ID精确匹配
4.1 postman中测试
{
"query": {
"ids" : {
"type" : "doc",
"values" : ["3", "4"]
}
}
}
4.2 java代码
//termQuery====>精确查询,不会对关键字分词
//searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));
//声明主键数组
String[] ids = new String[]{"3","4"};
//termsQuery ======>根据主键数组进行精确查询
searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
//设置分页
5.match Query全文检索
match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
match query与Term query区别是match query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。
5.1 postman中测试
{
"query": {
"match" : {
"desc" : {
"query" : "三体世界",
"operator" : "or"
}
}
}
}
query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用逗号分隔也可以不用。
operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。
5.2 java 代码
//searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
//matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
//设置分页
6.multi Query
6.1 postman中测试
multiQuery,一次可以匹配多个字段。
使用minimum_should_match可以指定文档匹配词的占比
匹配多个字段时可以提升字段的boost(权重)来提高得分
{
"query": {
"multi_match" : {
"query" : "世界",
"minimum_should_match": "50%",
"fields": [ "name", "desc" ]
}
}
}
{
"query": {
"multi_match" : {
"query" : "世界",
"minimum_should_match": "50%",
"fields": [ "name", "desc^10" ]
}
}
}
6.2 java代码
//searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
//mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
//设置分页
7.布尔查询
布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。
三个参数:
must:文档必须匹配must所包括的查询条件,相当于 “AND”
should:文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”
must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”
//声明主键数组
String[] ids = new String[]{"1","2","3","4"};
//termsQuery ======>根据主键数组进行精确查询
//searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
//如果是bool汇总查询,精确查询这样写
TermsQueryBuilder s = QueryBuilders.termsQuery("_id", ids);
//matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
//searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
//mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
// searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
//如果是bool汇总查询,mulitMatchQuery这样写
MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery("三体世界", "name", "desc").field("desc", 10);
//boolQuery=====>将上边的几个查询条件汇总到一起进行查询
//精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(s);
boolQueryBuilder.must(field);
// //将boolquery设置到搜索源对象中
searchSourceBuilder.query(boolQueryBuilder);
//设置分页
8.过滤器
range:范围过虑,保留大于等于60 并且小于等于100的记录。
term:项匹配过虑,保留studymodel等于"201001"的记录。
注意:range和term一次只能对一个Field设置范围过虑。
//boolQuery=====>将上边的几个查询条件汇总到一起进行查询
//精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(s);
boolQueryBuilder.must(field);
//rangeQuery 进行范围的过滤,过滤价格 .rangeQuery
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte("10").lte("50"));
// //将boolquery设置到搜索源对象中
searchSourceBuilder.query(boolQueryBuilder);
9.排序
可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序。
/ //将boolquery设置到搜索源对象中
searchSourceBuilder.query(boolQueryBuilder);
//设置排序
searchSourceBuilder.sort("id", SortOrder.DESC);
//设置分页
10 高亮显示
高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。
//设置排序
searchSourceBuilder.sort("id", SortOrder.DESC);
//设置高亮展示
HighlightBuilder highlightBuilder = new HighlightBuilder();
//设置前缀
highlightBuilder.preTags("<font style='color:red'>");
//设置后缀
highlightBuilder.postTags("</font>");
//设置高亮展示在那个字段上
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
highlightBuilder.fields().add(new HighlightBuilder.Field("desc"));
//将高亮设置到搜索对象中
searchSourceBuilder.highlighter(highlightBuilder);
//设置分页
//当前页码
int page = 1;//页码
int size = 5;//每页显示个数
int from = (page - 1) * size;//起记录下标
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//将搜索源对象设置到搜索请求客户端中
searchRequest.source(searchSourceBuilder);
//使用高版本的客户端进行搜索
SearchResponse search = highLevelClient.search(searchRequest);
//获取到 返回值,进行解析
SearchHits hits = search.getHits();
//从hits对象中获取到hits数组
SearchHit[] hits1 = hits.getHits();
//查询出的总条数
long totalHits = hits.getTotalHits();
System.out.println("当前查询出的总数为:"+totalHits);
//循环获取数据
for(SearchHit hit:hits1){
String id = hit.getId();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//从hit中获取高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
String name="";
if(highlightBuilder!=null){
HighlightField highlightName = highlightFields.get("name");
if(highlightName!=null){
Text[] fragments = highlightName.getFragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
name=stringBuffer.toString();
}
}
System.out.println("当前 高亮的字段为 name========="+name);
System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
多个字段高亮
//从hit中获取高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
String name="";
String desc="";
if(highlightBuilder!=null){
HighlightField highlightName = highlightFields.get("name");
HighlightField highlightDesc = highlightFields.get("desc");
if(highlightName!=null){
Text[] fragments = highlightName.getFragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
name=stringBuffer.toString();
}
if(highlightDesc!=null){
Text[] fragments = highlightDesc.getFragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
desc=stringBuffer.toString();
}
}
System.out.println("当前 高亮的字段为 name========="+name);
System.out.println("当前 高亮的字段为 desc========="+desc);
System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
11.完整代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class DSLTest {
@Autowired
RestHighLevelClient highLevelClient;
@Test
public void testSearch() throws IOException {
//声明搜索请求客户端
SearchRequest searchRequest = new SearchRequest("wang-003");
//设置请求类型
searchRequest.types("doc");
//构建搜索源对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//告诉搜索源对象,执行搜索时按照什么类型
//MatchAllQuery===>查询全部
//searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//termQuery====>精确查询,不会对关键字分词
//searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));
//声明主键数组
String[] ids = new String[]{"1","2","3","4"};
//termsQuery ======>根据主键数组进行精确查询
//searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
//如果是bool汇总查询,精确查询这样写
TermsQueryBuilder s = QueryBuilders.termsQuery("_id", ids);
//matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
//searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
//mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
// searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
//如果是bool汇总查询,mulitMatchQuery这样写
MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery("三体世界", "name", "desc").field("desc", 10);
//boolQuery=====>将上边的几个查询条件汇总到一起进行查询
//精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(s);
boolQueryBuilder.must(field);
//rangeQuery 进行范围的过滤,过滤价格 .rangeQuery
//boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte("10").lte("500"));
// //将boolquery设置到搜索源对象中
searchSourceBuilder.query(boolQueryBuilder);
//设置排序
searchSourceBuilder.sort("id", SortOrder.DESC);
//设置高亮展示
HighlightBuilder highlightBuilder = new HighlightBuilder();
//设置前缀
highlightBuilder.preTags("<font style='color:red'>");
//设置后缀
highlightBuilder.postTags("</font>");
//设置高亮展示在那个字段上
highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
highlightBuilder.fields().add(new HighlightBuilder.Field("desc"));
//将高亮设置到搜索对象中
searchSourceBuilder.highlighter(highlightBuilder);
//设置分页
//当前页码
int page = 1;//页码
int size = 5;//每页显示个数
int from = (page - 1) * size;//起记录下标
searchSourceBuilder.from(from);
searchSourceBuilder.size(size);
//将搜索源对象设置到搜索请求客户端中
searchRequest.source(searchSourceBuilder);
//使用高版本的客户端进行搜索
SearchResponse search = highLevelClient.search(searchRequest);
//获取到 返回值,进行解析
SearchHits hits = search.getHits();
//从hits对象中获取到hits数组
SearchHit[] hits1 = hits.getHits();
//查询出的总条数
long totalHits = hits.getTotalHits();
System.out.println("当前查询出的总数为:"+totalHits);
//循环获取数据
for(SearchHit hit:hits1){
String id = hit.getId();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//从hit中获取高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
String name="";
String desc="";
if(highlightBuilder!=null){
HighlightField highlightName = highlightFields.get("name");
HighlightField highlightDesc = highlightFields.get("desc");
if(highlightName!=null){
Text[] fragments = highlightName.getFragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
name=stringBuffer.toString();
}
if(highlightDesc!=null){
Text[] fragments = highlightDesc.getFragments();
StringBuffer stringBuffer = new StringBuffer();
for(Text text:fragments){
stringBuffer.append(text);
}
desc=stringBuffer.toString();
}
}
System.out.println("当前 高亮的字段为 name========="+name);
System.out.println("当前 高亮的字段为 desc========="+desc);
System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
}
}
}