ElasticSearch在Java中的一些API实现

查询全部

查询指定索引库指定类型下的文档。(通过使用此方法)

{
	"query": {
		"match_all": {}
	},
	"_source" : ["name","studymodel"]
}

_source:source源过虑设置,指定结果中所包括的字段有哪些。

结果说明:

took:本次操作花费的时间,单位为毫秒。

timed_out:请求是否超时

_shards:说明本次操作共搜索了哪些分片

hits:搜索命中的记录

hits.total : 符合条件的文档总数

hits.hits :匹配度较高的前N个文档

hits.max_score:文档匹配得分,这里为最高分

_score:每个文档都有一个匹配度得分,按照降序排列。

_source:显示了文档的原始内容。

Java Client

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDSL {

    @Autowired
    RestHighLevelClient restHighLevelClient;

    @Autowired
    RestClient restClient;

    //全部搜索
    @Test
    public void testSearchAll() throws IOException {
        //创建搜索对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //创建搜索源对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //搜索方式 搜索全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置源字段过滤 第一个参数是包括哪些字段,第二个参数是不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel"},new String[]{});
        //向搜索对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索
        SearchResponse response = restHighLevelClient.search(searchRequest);
        //搜索结果
        SearchHits hits = response.getHits();
        //匹配的总记录数
        long totalHits = hits.totalHits;
        //得到匹配度最高的文档
        SearchHit[] hitsHits = hits.getHits();
        for (SearchHit hit : hitsHits){
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            System.out.println(sourceAsMap);
        }
    }
}

分页查询

ES支持分页查询,传入两个参数:from和size。

form:表示起始文档的下标,从0开始。

size:查询的文档数量。

{ "
	from" : 0, "size" : 1,
	"query": {
		"match_all": {}
	},
	"_source" : ["name","studymodel"]
}

Java Client

SearchRequest searchRequest = new SearchRequest("xc_course");
searchRequest.types("xc_course");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//分页查询,设置起始下标,从0开始
searchSourceBuilder.from(0);
//每页显示个数
searchSourceBuilder.size(10);
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

Term Query

Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。

{
	"query": {
		"term" : {
			"name": "spring"
		}
	},
	"_source" : ["name","studymodel"]
}

上边的搜索会查询name包括“spring”这个词的文档。

Java Clien

SearchRequest searchRequest = new SearchRequest("xc_course");
searchRequest.types("xc_course");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("name","spring"));
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

根据id精确匹配

ES提供根据多个id值匹配的方法:

{
	"query": {
		"ids" : {
			"type" : "doc",
			"values" : ["3", "4", "100"]
		}
	}
}

Java Client

String[] split = new String[]{"1","2"};
List<String> idList = Arrays.asList(split);
searchSourceBuilder.query(QueryBuilders.termsQuery("_id", idList));

match Query

1、基本使用

match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

match query与Term query区别是match query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。

{
	"query": {
		"match" : {
			"description" : {
				"query" : "spring开发",
				"operator" : "or"
			}
		}
	}
}

query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。

operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。

上边的搜索的执行过程是:

1、将“spring开发”分词,分为spring、开发两个词

2、再使用spring和开发两个词去匹配索引中搜索。

3、由于设置了operator为or,只要有一个词匹配成功则就返回该文档。

Java Client

//根据关键字搜索
@Test
public void testMatchQuery() throws IOException {
	SearchRequest searchRequest = new SearchRequest("xc_course");
	searchRequest.types("xc_course");
	SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
	//source源字段过虑
	searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});
	//匹配关键字
	searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发").operator(Operator.OR));
	searchRequest.source(searchSourceBuilder);
	SearchResponse searchResponse = client.search(searchRequest);
	SearchHits hits = searchResponse.getHits();
	SearchHit[] searchHits = hits.getHits();
	for (SearchHit hit : searchHits) {
		String index = hit.getIndex();
		String type = hit.getType();
		String id = hit.getId();
		float score = hit.getScore();
		String sourceAsString = hit.getSourceAsString();
		Map<String, Object> sourceAsMap = hit.getSourceAsMap();
		String name = (String) sourceAsMap.get("name");
		String studymodel = (String) sourceAsMap.get("studymodel");
        String description = (String) sourceAsMap.get("description");
        System.out.println(name);
        System.out.println(studymodel);
        System.out.println(description);
	}
}

2、minimum_should_match

上边使用的operator = or表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现

使用minimum_should_match可以指定文档匹配词的占比:

比如搜索语句如下:

{
	"query": {
		"match" : {
        "description" : {
        	"query" : "spring开发框架",
        	"minimum_should_match": "80%"
       		}
        }
    }
}

“spring开发框架”会被分为三个词:spring、开发、框架

设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表 示至少有两个词在文档中要匹配成功。

Java Client

//匹配关键字
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "前台页面开发框架 架构").minimumShouldMatch("80%");//设置匹配占比
searchSourceBuilder.query(matchQueryBuilder);

multi Query

上边学习的termQuery和matchQuery一次只能匹配一个Field,本节学习multiQuery,一次可以匹配多个字段。

1、基本使用 单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。

拿关键字 “spring css”去匹配name 和description字段

{
    "query": {
        "multi_match" : {
            "query" : "spring css",
            "minimum_should_match": "50%",
            "fields": [ "name", "description" ]
    	}
    }
}

2、提升boost

匹配多个字段时可以提升字段的boost(权重)来提高得分

提升boost,通常关键字匹配上name的权重要比匹配上description的权重高,这里可以对name的权重提升。

{
	"query": {
		"multi_match" : {
            "query" : "spring框架",
            "minimum_should_match": "50%",
            "fields": [ "name^10", "description" ]
		}
	}
}

“name^10” 表示权重提升10倍,执行上边的查询,发现name中包括spring关键字的文档排在前边。

Java Client

MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架",
"name", "description").minimumShouldMatch("50%");
multiMatchQueryBuilder.field("name",10);//提升boost

布尔查询

布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。

三个参数:

  • must:文档必须匹配must所包括的查询条件,相当于 “AND”
  • should:文档应该匹配should所包括的查询条件其 中的一个或多个,相当于 “OR”
  • must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”

分别使用must、should、must_not测试下边的查询:

{
    "_source" : [ "name", "studymodel", "description"],
    "from" : 0, "size" : 1,
        "query": {
            "bool" : {
            "must":[
                {
                    "multi_match" : {
                        "query" : "spring框架",
                        "minimum_should_match": "50%",
                        "fields": [ "name^10", "description" ]
                    }
                },
                {
                    "term":{
                    	"studymodel" : "201001"
                    }
                }
            ]
        }
    }
}

must:表示必须,多个查询条件必须都满足。(通常使用must)

should:表示或者,多个查询条件只要有一个满足即可。

must_not:表示非。

Java Client

//BoolQuery,将搜索关键字分词,拿分词去索引库搜索
@Test
public void testBoolQuery() throws IOException {
	//创建搜索请求对象
	SearchRequest searchRequest= new SearchRequest("xc_course");
	searchRequest.types("doc");
	//创建搜索源配置对象
	SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
	searchSourceBuilder.fetchSource(new String[]{"name","pic","studymodel"},new String[]{});
	//multiQuery
	String keyword = "spring开发框架";
	MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架",
	"name", "description").minimumShouldMatch("50%");
	multiMatchQueryBuilder.field("name",10);
	//TermQuery
	TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
	//布尔查询
	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
	boolQueryBuilder.must(multiMatchQueryBuilder);
	boolQueryBuilder.must(termQueryBuilder);
	//设置布尔查询对象
	searchSourceBuilder.query(boolQueryBuilder);
	searchRequest.source(searchSourceBuilder);//设置搜索源配置
	SearchResponse searchResponse = client.search(searchRequest);
	SearchHits hits = searchResponse.getHits();
	SearchHit[] searchHits = hits.getHits();
	for(SearchHit hit:searchHits){
		Map<String, Object> sourceAsMap = hit.getSourceAsMap();
		System.out.println(sourceAsMap);
	}
}

过滤器

过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过 虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。

过虑器在布尔查询中使用,下边是在搜索结果的基础上进行过虑:

{
	"_source": ["name", "studymodel", "description", "price"],
	"query": {
		"bool": {
			"must": [{
				"multi_match": {
					"query": "spring框架",
					"minimum_should_match": "50%",
					"fields": ["name^10", "description"]
				}
			}],
			"filter": [{
					"term": {
						"studymodel": "201001"
					}
				},
				{
					"range": {
						"price": {
							"gte": 60,
							"lte": 100
						}
					}
				}
			]
		}
	}
}

range:范围过虑,保留大于等于60 并且小于等于100的记录。

term:项匹配过虑,保留studymodel等于"201001"的记录。

注意:range和term一次只能对一个Field设置范围过虑。

Java Client

//布尔查询使用过虑器
@Test
public void testFilter() throws IOException {
    SearchRequest searchRequest = new SearchRequest("xc_course");
    searchRequest.types("doc");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //source源字段过虑
    searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},
    new String[]{});
    searchRequest.source(searchSourceBuilder);
    //匹配关键字
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框
    架", "name", "description");
    //设置匹配占比
    multiMatchQueryBuilder.minimumShouldMatch("50%");
    //提升另个字段的Boost值
    multiMatchQueryBuilder.field("name",10);
    searchSourceBuilder.query(multiMatchQueryBuilder);
    //布尔查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(searchSourceBuilder.query());
    //过虑
    boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"));
    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
    SearchResponse searchResponse = client.search(searchRequest);
    SearchHits hits = searchResponse.getHits();
    SearchHit[] searchHits = hits.getHits();
    for (SearchHit hit : searchHits) {
        String index = hit.getIndex();
        String type = hit.getType();
        String id = hit.getId();
        float score = hit.getScore();
        String sourceAsString = hit.getSourceAsString();
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        String name = (String) sourceAsMap.get("name");
        String studymodel = (String) sourceAsMap.get("studymodel");
        String description = (String) sourceAsMap.get("description");
        System.out.println(name);
        System.out.println(studymodel);
        System.out.println(description);
    }
}

排序

可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排 序。

发送 POST http://localhost:9200/xc_course/doc/_search

过虑0–100元价格范围的文档,并且对结果进行排序,先按studymodel降序,再按价格升序

{
	"_source": ["name", "studymodel", "description", "price"],
	"query": {
		"bool": {
			"filter": [{
				"range": {
					"price": {
						"gte": 0,
						"lte": 100
					}
				}
			}]
		}
	},
	"sort": [{
			"studymodel": "desc"
		},
		{
			"price": "asc"
		}
	]
}

Java Client



高亮显示

高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。

在搜索语句中添加highlight即可实现,如下:

{
	"_source": ["name", "studymodel", "description", "price"],
	"query": {
		"bool": {
			"must": [{
				"multi_match": {
					"query": "开发框架",
					"minimum_should_match": "50%",
					"fields": ["name^10", "description"],
					"type": "best_fields"
				}
			}],
			"filter": [{
				"range": {
					"price": {
						"gte": 0,
						"lte": 100
					}
				}
			}]
		}
	},
	"sort": [{
		"price": "asc"
	}],
	"highlight": {
		"pre_tags": ["<tag>"],
		"post_tags": ["</tag>"],
		"fields": {
			"name": {},
			"description": {}
		}
	}
}

Java Client

@Test
public void testHighlight() throws IOException {
    SearchRequest searchRequest = new SearchRequest("xc_course");
    searchRequest.types("doc");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //source源字段过虑
    searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},
    new String[]{});
    searchRequest.source(searchSourceBuilder);
    //匹配关键字
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发",
    "name", "description");
    searchSourceBuilder.query(multiMatchQueryBuilder);
    //布尔查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(searchSourceBuilder.query());
    //过虑
    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
    //排序
    searchSourceBuilder.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));
    searchSourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));
    //高亮设置
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.preTags("<tag>");//设置前缀
    highlightBuilder.postTags("</tag>");//设置后缀
    // 设置高亮字段
    highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
    // highlightBuilder.fields().add(new HighlightBuilder.Field("description"));
    searchSourceBuilder.highlighter(highlightBuilder);
    SearchResponse searchResponse = client.search(searchRequest);
    SearchHits hits = searchResponse.getHits();
    SearchHit[] searchHits = hits.getHits();
    for (SearchHit hit : searchHits) {
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        //名称
        String name = (String) sourceAsMap.get("name");
        //取出高亮字段内容
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        if(highlightFields!=null){
            HighlightField nameField = highlightFields.get("name");
            if(nameField!=null){
                Text[] fragments = nameField.getFragments();
                StringBuffer stringBuffer = new StringBuffer();
                for (Text str : fragments) {
                    stringBuffer.append(str.string());
                } 
                name = stringBuffer.toString();
            }
        } 
        String index = hit.getIndex();
        String type = hit.getType();
        String id = hit.getId();
        float score = hit.getScore();
        String sourceAsString = hit.getSourceAsString();
        String studymodel = (String) sourceAsMap.get("studymodel");
        String description = (String) sourceAsMap.get("description");
        System.out.println(name);
        System.out.println(studymodel);
        System.out.println(description);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值