一。多字段查询QueryString

流程:

  • 会对查询条件进行分词。
  • 然后将分词后的查询条件和词条进行等值匹配
  • 默认取并集(OR)
  • 可以指定多个查询字段

1.1 restAPI

例:在title和brandName字段中只要有一个字段包含“小米手机”分词字样的话,都查出来:

GET goods/_search
{
  "query": {
    "query_string": {
      "fields": ["title","categoryName","brandName"],
      "query": "苹果手机"
    }
  }
}

例: title 和 brandName中都得包含“小米”或“手机”:

GET goods/_search
{
  "query": {
    "query_string": {
      "fields": ["title","brandName"],
      "query": "小米 AND 手机"
    }
  }
}

例 :title name字段中有一个字段包含 华为 或 手机 或 AND 三个分词就行,查询粒度大。
不支持连接符,按照“华为”“AND”“手机” 三个词查询:

GET goods/_search
{
  "query": {
    "simple_query_string": {
      "fields": ["title","categoryName","brandName"],
      "query": "华为 AND 手机"
    }
  }
}

1.2 javaAPI

@Test
    public void testStringQuery() throws IOException {
//        1.创建请求
        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
       ★★★ QueryStringQueryBuilder field = QueryBuilders.queryStringQuery("小米 AND 手机").field("title").field("brandName");
        searchSourceBuilder.query(field);

        searchSourceBuilder.sort("price", SortOrder.DESC);

        searchRequest.source(searchSourceBuilder);
//        2.执行操作
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

//        3.获取结果
        List<Goods> goodsList = new ArrayList<>();
        SearchHits hits = searchResponse.getHits();
        long value = hits.getTotalHits().value;
        System.out.println(value);
        SearchHit[] smallHits = hits.getHits();
        for (SearchHit smallHit : smallHits) {
            String sourceAsString = smallHit.getSourceAsString();
            Goods goods = JSON.parseObject(sourceAsString, Goods.class);
            goodsList.add(goods);
        }
        for (Goods goods : goodsList) {
            System.out.println(goods);
        }

    }
SimpleQueryString:
QueryBuilders.simpleQueryStringQuery("小米 AND 手机").field("title").field("brandName");

二。布尔查询

2.1 rest:

1概念:
多个查询条件连接

2链接方式:

  • must(and):条件必须成立
  • must_not(not):条件必须不成立
  • should(or):条件可以成立
  • filter:条件必须成立,性能比must高。负责上面三个条件查询结果的过滤。不会计算相关度score,因为耗性能。主要放: range 1000-2000,term 华为 。
# title必须包含手机,品牌必须小米,品牌可以是诺基亚,不能是华为,价格1000-2000
GET goods/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "手机"
          }
        },
        {
          "term": {
            "brandName": {
              "value": "小米"
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "brandName": {
              "value": "诺基亚"
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "brandName": {
              "value": "华为"
            }
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 1000,
              "lte": 2000
            }
          }
        }
      ]
    }
  }
}

2.2 java:

@Test
    public void testBoolQuery() throws IOException {
//        1.创建请求
        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        boolQueryBuilder.must(matchQueryBuilder);
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brandName", "小米");
        boolQueryBuilder.must(termQueryBuilder);
        TermQueryBuilder termQueryBuilder1 = QueryBuilders.termQuery("brandName", "诺基亚");
        boolQueryBuilder.should(termQueryBuilder1);
        TermQueryBuilder termQueryBuilder2 = QueryBuilders.termQuery("brandName", "华为");
        boolQueryBuilder.mustNot(termQueryBuilder2);
        RangeQueryBuilder price = QueryBuilders.rangeQuery("price").gte(1000).lte(2000);
        boolQueryBuilder.filter(price);

        searchSourceBuilder.query(boolQueryBuilder);

        searchRequest.source(searchSourceBuilder);
//        2.执行操作
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

//        3.获取结果
        List<Goods> goodsList = new ArrayList<>();
        SearchHits hits = searchResponse.getHits();
        long value = hits.getTotalHits().value;
        System.out.println(value);
        SearchHit[] smallHits = hits.getHits();
        for (SearchHit smallHit : smallHits) {
            String sourceAsString = smallHit.getSourceAsString();
            Goods goods = JSON.parseObject(sourceAsString, Goods.class);
            goodsList.add(goods);
        }
        for (Goods goods : goodsList) {
            System.out.println(goods);
        }

    }

三。agg聚合查询

查询出结果以后,再把结果进行聚合。所以agg聚合是和query平行

3.1 rest

# 每个品牌手机的个数
# select brandName count(1) as group_by_brandName from goods where title like "%手机%" group by brandName

GET goods/_search
{
 "query": {
   "match": {
     "title": "手机"
   }
 },
 "aggs": {
   "group_by_brandName": {
     "terms": {
       "field": "brandName"
     }
   }
 }
}

聚合查询结果:

"aggregations" : {
    "group_by_brandName" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 113,
      "buckets" : [
        {
          "key" : "三星",
          "doc_count" : 127
        },
        {
          "key" : "苹果",
          "doc_count" : 93
        },
        {
          "key" : "中国移动",
          "doc_count" : 79
        },
        {
          "key" : "联想",
          "doc_count" : 68
        },
        {
          "key" : "华为",
          "doc_count" : 66
        },
        {
          "key" : "酷派",
          "doc_count" : 44
        },
        {
          "key" : "诺基亚",
          "doc_count" : 41
        },
        {
          "key" : "飞利浦",
          "doc_count" : 33
        },
        {
          "key" : "OPPO",
          "doc_count" : 30
        },
        {
          "key" : "HTC",
          "doc_count" : 23
        }
      ]
    }
  }

3.2 java

@Test
    public void testAggQuery() throws IOException {
//        1.创建请求
        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        searchSourceBuilder.query(matchQueryBuilder);
//     不要具体数据
        searchSourceBuilder.size(0);
//      设置聚合
        TermsAggregationBuilder group_by_brandName = AggregationBuilders.terms("group_by_brandName").field("brandName");
        searchSourceBuilder.aggregation(group_by_brandName);


        searchRequest.source(searchSourceBuilder);
//        2.执行操作
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

//        3.获取聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        Terms aggregation = aggregations.get("group_by_brandName");
        List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String keyAsString = bucket.getKeyAsString();
            System.out.println(keyAsString);
            long docCount = bucket.getDocCount();
            System.out.println(docCount);
        }
    }

3.3 查询手机均价 restAPI

# 手机均价?
# select avg(price) as avg_price from goods  where title like "%手机%" 
GET goods/_search
{
 "query": {
   "match": {
     "title": "手机"
   }
 },
 "size": 0,                 
 "aggs": {
   "avg_price": {
     "avg": {
       "field": "price"
     }
   }
 }
}

3.4 查询手机均价 javaAPI

@Test
    public void testAggQuery2() throws IOException {
//        1.创建请求
        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        searchSourceBuilder.query(matchQueryBuilder);
//     不要具体hits数据,只看聚合结果
        searchSourceBuilder.size(0);
//      设置聚合
        AvgAggregationBuilder avg_price = AggregationBuilders.avg("avg_price").field("price");
        searchSourceBuilder.aggregation(avg_price);


        searchRequest.source(searchSourceBuilder);
//        2.执行操作
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

//        3.获取聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        Avg aggregation = aggregations.get("avg_price");
        double value = aggregation.getValue();
        System.out.println(value);
    }

四。subagg子聚合

4.1 rest

# 每个品牌手机的均价
# select brandName avg(price) as avg_price from goods where title like "%手机%" group by brandName
GET goods/_search
{
 "query": {
   "match": {
     "title": "手机"
   }
 },
 "size": 0,                 
 "aggs": {
   "group_brand": {
     "terms": {
       "field": "brandName"
     },
    "aggs": {
      "avg_brand": {
        "avg": {
          "field": "price"
        }
      }
    }
   }
 }
}

部分结果:

"aggregations" : {
    "group_brand" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 113,
      "buckets" : [
        {
          "key" : "三星",
          "doc_count" : 127,
          "avg_brand" : {
            "value" : 3013.48031496063
          }
        },
        {
          "key" : "苹果",
          "doc_count" : 93,
          "avg_brand" : {
            "value" : 5626.763440860215
          }
        },......

4.2java

@Test
    public void testAggQuery3() throws IOException {
//        1.创建请求
        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "手机");
        searchSourceBuilder.query(matchQueryBuilder);
//     不要具体数据 ,只显示聚合出来的结果
        searchSourceBuilder.size(0);
//      设置聚合
        TermsAggregationBuilder group_by_brandName = AggregationBuilders.terms("group_brand").field("brandName");
        AvgAggregationBuilder field = AggregationBuilders.avg("avg_brand").field("price");
//  subagg 父聚合中的子聚合
        group_by_brandName.subAggregation(field);


        searchSourceBuilder.aggregation(group_by_brandName);


        searchRequest.source(searchSourceBuilder);
//        2.执行操作
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

//        3.获取聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        Terms aggregation = aggregations.get("group_brand");
        List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String keyAsString = bucket.getKeyAsString();
            System.out.println(keyAsString);
            long docCount = bucket.getDocCount();
            System.out.println(docCount);
            Aggregations aggregations1 = bucket.getAggregations();
            Avg avg_brand = aggregations1.get("avg_brand");  //拿到具体聚合
            System.out.println(avg_brand.getValue());
        }
    }