ES查詢
matchAll
腳本方式
該方式可以通過kabana、curl、elasticsearch-head(純前端)去操作
# 默認(rèn)情況下,es一次展示10條數(shù)據(jù),通過from和size來控制分頁
# 查詢結(jié)果詳解
GET goods/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 100
}
# 默認(rèn)為10條
GET goods
Java API方式
/**
* 查詢所有
* 1. matchAll
* 2. 將查詢結(jié)果封裝為Goods對象,裝載到List中
* 3. 分頁。默認(rèn)顯示10條
*/
@Test
public void testMatchAll() throws IOException {
//2. 構(gòu)建查詢請求對象,指定查詢的索引名稱
SearchRequest searchRequest = new SearchRequest("goods");
//4. 創(chuàng)建查詢條件構(gòu)建器SearchSourceBuilder
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//6. 查詢條件
QueryBuilder query = QueryBuilders.matchAllQuery();//查詢所有文檔
//5. 指定查詢條件
sourceBuilder.query(query);
//3. 添加查詢條件構(gòu)建器 SearchSourceBuilder
searchRequest.source(sourceBuilder);
// 8 . 添加分頁信息
sourceBuilder.from(0);
sourceBuilder.size(100);
//1. 查詢,獲取查詢結(jié)果
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//7. 獲取命中對象 SearchHits
SearchHits searchHits = searchResponse.getHits();
//7.1 獲取總記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
//7.2 獲取Hits數(shù)據(jù) 數(shù)組
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
//獲取json字符串格式的數(shù)據(jù)
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java對象
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
termQuery
term查詢和字段類型有關(guān)系,首先回顧一下ElasticSearch兩個(gè)數(shù)據(jù)類型
ElasticSearch兩個(gè)數(shù)據(jù)類型
1、text:會分詞,不支持聚合
2、keyword:不會分詞,將全部內(nèi)容作為一個(gè)詞條,支持聚合
腳本方式
term查詢:不會對查詢條件進(jìn)行分詞。
GET goods/_search
{
"query": {
"term": {
"title": {
"value": "華為"
}
}
}
}
term查詢,查詢text類型字段時(shí),只有其中的單詞相匹配都會查到,text字段會對數(shù)據(jù)進(jìn)行分詞
例如:查詢title 為“華為”的,title type 為text
"title": {
"type": "text",
"analyzer": "ik_smart"
}
查詢categoryName 字段時(shí),categoryName字段為keyword ,keyword:不會分詞,將全部內(nèi)容作為一個(gè)詞條,即完全匹配,才能查詢出結(jié)果.
GET goods/_search
{
"query": {
"term": {
"categoryName": {
"value": "華為手機(jī)"
}
}
}
}
Java API
/**
* termQuery:詞條查詢
*/
@Test
public void testTermQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
QueryBuilder query = QueryBuilders.termQuery("title","華為");//term詞條查詢
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
matchQuery
match查詢:
?會對查詢條件進(jìn)行分詞。
?然后將分詞后的查詢條件和詞條進(jìn)行等值匹配
?默認(rèn)取并集(OR)
?
# match查詢
GET goods/_search
{
"query": {
"match": {
"title": "華為手機(jī)"
}
},
"size": 500
}
match 的默認(rèn)搜索(or 并集)
例如:華為手機(jī),會分詞為 “華為”,“手機(jī)” 只要出現(xiàn)其中一個(gè)詞條都會搜索到
match的 and(交集) 搜索
例如:例如:華為手機(jī),會分詞為 “華為”,“手機(jī)” 但要求“華為”,和“手機(jī)”同時(shí)出現(xiàn)在詞條中
?
總結(jié):
term query會去倒排索引中尋找確切的term,它并不知道分詞器的存在。這種查詢適合keyword
、numeric、date
match query知道分詞器的存在。并且理解是如何被分詞的
?
java api
/**
* matchQuery:詞條分詞查詢
*/
@Test
public void testMatchQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "華為手機(jī)");
query.operator(Operator.AND);//求并集
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
模糊查詢-腳本 ?
wildcard查詢 ?
wildcard查詢:會對查詢條件進(jìn)行分詞。還可以使用通配符 ?(任意單個(gè)字符) 和 * (0個(gè)或多個(gè)字符)
*華*" 包含華字的
"華*" 華字后邊多個(gè)字符
"華?" 華字后邊多個(gè)字符
"*華"或"?華" 會引發(fā)全表(全索引)掃描 注意效率問題
# wildcard 查詢。查詢條件分詞,模糊查詢
GET goods/_search
{
"query": {
"wildcard": {
"title": {
"value": "華*"
}
}
}
}
正則查詢 ?
\W:匹配包括下劃線的任何單詞字符,等價(jià)于 [A-Z a-z 0-9_] 開頭的反斜杠是轉(zhuǎn)義符
+號多次出現(xiàn)
(.)*為任意字符
正則查詢?nèi)Q于正則表達(dá)式的效率
?
GET goods/_search
{
"query": {
"regexp": {
"title": "\\w+(.)*"
}
}
}
前綴查詢
#前綴查詢 對keyword類型支持比較好
GET goods/_search
{
"query": {
"prefix": {
"brandName": {
"value": "三"
}
}
}
}
?模糊查詢- Java Api
/**
* 模糊查詢:WildcardQuery
*/
@Test
public void testWildcardQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
WildcardQueryBuilder query = QueryBuilders.wildcardQuery("title", "華*");
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
/**
* 模糊查詢:regexpQuery
*/
@Test
public void testRegexpQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
RegexpQueryBuilder query = QueryBuilders.regexpQuery("title", "\\w+(.)*");
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
/**
* 模糊查詢:perfixQuery
*/
@Test
public void testPrefixQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
PrefixQueryBuilder query = QueryBuilders.prefixQuery("brandName", "三");
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
范圍和排序
# 范圍查詢
GET goods/_search
{
"query": {
"range": {
"price": {
"gte": 2000,
"lte": 3000
}
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
/**
* 1. 范圍查詢:rangeQuery
* 2. 排序
*/
@Test
public void testRangeQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
//范圍查詢
RangeQueryBuilder query = QueryBuilders.rangeQuery("price");
//指定下限
query.gte(2000);
//指定上限
query.lte(3000);
sourceBulider.query(query);
//排序
sourceBulider.sort("price", SortOrder.DESC);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
queryString查詢 ?
queryString 多條件查詢
?會對查詢條件進(jìn)行分詞。
?然后將分詞后的查詢條件和詞條進(jìn)行等值匹配
?默認(rèn)取并集(OR)
?可以指定多個(gè)查詢字段
query_string:識別query中的連接符(or 、and)
?
# queryString
GET goods/_search
{
"query": {
"query_string": {
"fields": ["title","categoryName","brandName"],
"query": "華為 AND 手機(jī)"
}
}
}
#simple_query_string:不識別query中的連接符(or 、and),查詢時(shí)會將 “華為”、"and"、“手機(jī)”分別進(jìn)行查詢
GET goods/_search
{
"query": {
"simple_query_string": {
"fields": ["title","categoryName","brandName"],
"query": "華為 AND 手機(jī)"
}
}
}
# simple_query_string:有default_operator連接符的腳本
GET goods/_search
{
"query": {
"simple_query_string": {
"fields": ["title","brandName","categoryName"],
"query": "華為手機(jī) "
, "default_operator": "OR"
}
}
}
// 注意:query中的or and 是查詢時(shí) 匹配條件是否同時(shí)出現(xiàn)----or 出現(xiàn)一個(gè)即可,and 兩個(gè)條件同時(shí)出現(xiàn)default_operator的or and 是對結(jié)果進(jìn)行 并集(or)、交集(and)
query_string:有default_operator連接符的腳本
GET goods/_search
{
"query": {
"query_string": {
"fields": ["title","brandName","categoryName"],
"query": "華為手機(jī) ",
"default_operator": "AND"
}
}
}
Java API
/**
* queryString
*/
@Test
public void testQueryStringQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
//queryString
QueryStringQueryBuilder query = QueryBuilders.queryStringQuery("華為手機(jī)").field("title").field("categoryName").field("brandName").defaultOperator(Operator.AND);
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
布爾查詢
boolQuery:對多個(gè)查詢條件連接。連接方式:
?must(and):條件必須成立
?must_not(not):條件必須不成立
?should(or):條件可以成立
?filter:條件必須成立,性能比must高。不會計(jì)算得分
得分:即條件匹配度,匹配度越高,得分越高
eg:?布爾查詢:boolQuery
1. 查詢品牌名稱為:華為
2. 查詢標(biāo)題包含:手機(jī)
3. 查詢價(jià)格在:2000-3000
#boolquery
#must和filter配合使用時(shí),max_score(得分)是顯示的
#must 默認(rèn)數(shù)組形式
GET goods/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"brandName": {
"value": "華為"
}
}
}
],
"filter":[
{
"term": {
"title": "手機(jī)"
}
},
{
"range":{
"price": {
"gte": 2000,
"lte": 3000
}
}
}
]
}
}
}
#filter 單獨(dú)使用 filter可以是單個(gè)條件,也可多個(gè)條件(數(shù)組形式)
GET goods/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"brandName": {
"value": "華為"
}
}
}
]
}
}
}
?java api
/**
* 布爾查詢:boolQuery
* 1. 查詢品牌名稱為:華為
* 2. 查詢標(biāo)題包含:手機(jī)
* 3. 查詢價(jià)格在:2000-3000
*/
@Test
public void testBoolQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
//1.構(gòu)建boolQuery
BoolQueryBuilder query = QueryBuilders.boolQuery();
//2.構(gòu)建各個(gè)查詢條件
//2.1 查詢品牌名稱為:華為
QueryBuilder termQuery = QueryBuilders.termQuery("brandName","華為");
query.must(termQuery);
//2.2. 查詢標(biāo)題包含:手機(jī)
QueryBuilder matchQuery = QueryBuilders.matchQuery("title","手機(jī)");
query.filter(matchQuery);
//2.3 查詢價(jià)格在:2000-3000
QueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
((RangeQueryBuilder) rangeQuery).gte(2000);
((RangeQueryBuilder) rangeQuery).lte(3000);
query.filter(rangeQuery);
//3.使用boolQuery連接
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
}
聚合查詢
指標(biāo)聚合:相當(dāng)于MySQL的聚合函數(shù)。max、min、avg、sum等
?桶聚合:相當(dāng)于MySQL的 group by 操作。不要對text類型的數(shù)據(jù)進(jìn)行分組,會失敗。
?
# 聚合查詢
# 指標(biāo)聚合 聚合函數(shù)
GET goods/_search
{
"query": {
"match": {
"title": "手機(jī)"
}
},
"aggs": {
"max_price": {
"max": {
"field": "price"
}
}
}
}
#桶聚合 分組
GET goods/_search
{
"query": {
"match": {
"title": "手機(jī)"
}
},
"aggs": {
"goods_brands": {
"terms": {
"field": "brandName",
"size": 100
}
}
}
}
java api
/**
* 聚合查詢:桶聚合,分組查詢
* 1. 查詢title包含手機(jī)的數(shù)據(jù)
* 2. 查詢品牌列表
*/
@Test
public void testAggQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
// 1. 查詢title包含手機(jī)的數(shù)據(jù)
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手機(jī)");
sourceBulider.query(query);
// 2. 查詢品牌列表
/*
參數(shù):
1. 自定義的名稱,將來用于獲取數(shù)據(jù)
2. 分組的字段
*/
AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100);
sourceBulider.aggregation(agg);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
// 獲取聚合結(jié)果
Aggregations aggregations = searchResponse.getAggregations();
Map<String, Aggregation> aggregationMap = aggregations.asMap();
//System.out.println(aggregationMap);
Terms goods_brands = (Terms) aggregationMap.get("goods_brands");
List<? extends Terms.Bucket> buckets = goods_brands.getBuckets();
List brands = new ArrayList();
for (Terms.Bucket bucket : buckets) {
Object key = bucket.getKey();
brands.add(key);
}
for (Object brand : brands) {
System.out.println(brand);
}
}
高亮查詢
高亮三要素:
?高亮字段
?前綴
?后綴
默認(rèn)前后綴 :em
?文章來源:http://www.zghlxwxcb.cn/news/detail-852429.html
GET goods/_search
{
"query": {
"match": {
"title": "電視"
}
},
"highlight": {
"fields": {
"title": {
"pre_tags": "<font color='red'>",
"post_tags": "</font>"
}
}
}
}
java api文章來源地址http://www.zghlxwxcb.cn/news/detail-852429.html
/**
*
* 高亮查詢:
* 1. 設(shè)置高亮
* * 高亮字段
* * 前綴
* * 后綴
* 2. 將高亮了的字段數(shù)據(jù),替換原有數(shù)據(jù)
*/
@Test
public void testHighLightQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
// 1. 查詢title包含手機(jī)的數(shù)據(jù)
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手機(jī)");
sourceBulider.query(query);
//設(shè)置高亮
HighlightBuilder highlighter = new HighlightBuilder();
//設(shè)置三要素
highlighter.field("title");
highlighter.preTags("<font color='red'>");
highlighter.postTags("</font>");
sourceBulider.highlighter(highlighter);
// 2. 查詢品牌列表
/*
參數(shù):
1. 自定義的名稱,將來用于獲取數(shù)據(jù)
2. 分組的字段
*/
AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100);
sourceBulider.aggregation(agg);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
//獲取記錄數(shù)
long value = searchHits.getTotalHits().value;
System.out.println("總記錄數(shù):"+value);
List<Goods> goodsList = new ArrayList<>();
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
//轉(zhuǎn)為java
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
// 獲取高亮結(jié)果,替換goods中的title
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField HighlightField = highlightFields.get("title");
Text[] fragments = HighlightField.fragments();
//替換
goods.setTitle(fragments[0].toString());
goodsList.add(goods);
}
for (Goods goods : goodsList) {
System.out.println(goods);
}
// 獲取聚合結(jié)果
Aggregations aggregations = searchResponse.getAggregations();
Map<String, Aggregation> aggregationMap = aggregations.asMap();
//System.out.println(aggregationMap);
Terms goods_brands = (Terms) aggregationMap.get("goods_brands");
List<? extends Terms.Bucket> buckets = goods_brands.getBuckets();
List brands = new ArrayList();
for (Terms.Bucket bucket : buckets) {
Object key = bucket.getKey();
brands.add(key);
}
for (Object brand : brands) {
System.out.println(brand);
}
}
到了這里,關(guān)于架構(gòu)師系列-搜索引擎ElasticSearch(四)- 高級查詢的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!