ES-Java-API


···1.ES Java API

https://www.bilibili.com/video/BV1Qz411e7yx?t=417&p=13

1.1 创建索引

@SpringBootTest
class Test2 {
    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    String index = "test2";

    @Test
    public void test1() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(index);
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.startObject("properties");
            {
                builder.startObject("name");
                {
                    builder.field("type", "text");
                }
                builder.endObject();
                builder.startObject("age");
                {
                    builder.field("type", "long");
                }
                builder.endObject();
                builder.startObject("des");
                {
                    builder.field("type", "text")
                        //插入时分词
                        .field("analyzer", "ik_smart")
                        //搜索时分词
                        .field("search_analyzer", "ik_max_word");
                }
                builder.endObject();
            }
            builder.endObject();
        }
        builder.endObject();
        request.mapping(builder);
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response);
    }
}

1.2 删除索引

@Test
public void test3() throws IOException {
    DeleteIndexRequest request = new DeleteIndexRequest("test2");
    AcknowledgedResponse delete = client.indices().delete(request,RequestOptions.DEFAULT);
    System.out.println(delete.isAcknowledged());
}

1.3 判断存在

@Test
public void test2() throws IOException {
    GetIndexRequest request = new GetIndexRequest(index);
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    System.out.println(exists);
}

1.4 插入文档

@Test
public void test4() throws IOException {
    IndexRequest request = new IndexRequest(index);
    request.id("5");
    Person person = new Person("刘华强", 22, "帅哥");
    request.source(JSON.toJSONString(person), XContentType.JSON);
    IndexResponse response = client.index(request, RequestOptions.DEFAULT);
    System.out.println(response.getResult());
}


@Test
public void addDoc() throws IOException {
    // 创建对象
    User user = new User("华强说", 22);
    // 创建请求
    IndexRequest request = new IndexRequest("lhq_index");

    // 规则  PUT /lhq_index/_doc/1
    request.id("1");
    request.timeout(TimeValue.timeValueSeconds(1));
    request.timeout("1s");
    // 将数据放入请求json
    request.source(JSON.toJSONString(user), XContentType.JSON);

    //客户端发送请求 , 获取响应结果
    IndexResponse index = client.index(request, RequestOptions.DEFAULT);
    System.out.println(index.toString());
    System.out.println(index.status());

}

1.5 更新文档

@Test
public void test5() throws IOException {
    UpdateRequest request = new UpdateRequest(index,"5");
    HashMap<String, Object> map = new HashMap<>();
    map.put("des","非常帅");
    request.doc(map);
    UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
    System.out.println(response.status());

}



// 更新文档
@Test
public void updateDoc() throws IOException {
    UpdateRequest request = new UpdateRequest("lhq_index", "1");
    request.timeout("1s");
    User user = new User("华强说Java", 20);
    UpdateRequest updateRequest = request.doc(JSON.toJSONString(user), XContentType.JSON);
    UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
    System.out.println(update.status());
}

1.6 删除文档

@Test
public void test6() throws IOException {
    DeleteRequest request = new DeleteRequest(index);
    request.id("5");

    DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
    System.out.println(response.status());
}

@Test
public void deleteDoc() throws IOException {
    DeleteRequest request = new DeleteRequest("lhq_index", "1");
    request.timeout("1s");
    DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
    System.out.println(delete.status());
}

1.7 批量操作

@Test
public void test7() throws IOException {
    BulkRequest bulkRequest = new BulkRequest();
    Person person1 = new Person("张三", 20, "无名之辈1");
    Person person2 = new Person("李四", 25, "无名之辈2");
    Person person3 = new Person("王麻子", 30, "无名之辈3");
    ArrayList<Person> arrayList = new ArrayList<>();
    arrayList.add(person1);
    arrayList.add(person2);
    arrayList.add(person3);
    for (int i = 0; i < arrayList.size(); i++) {
        bulkRequest.add(new IndexRequest(index).id(i + 1 + "").source(JSON.toJSONString(arrayList.get(i)), XContentType.JSON));
    }

    BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(response);
}

1.8 批量删除

@Test
public void test8() throws IOException {
    BulkRequest bulkRequest = new BulkRequest();

    for (int i = 0; i < 3; i++) {
        bulkRequest.add(new DeleteRequest(index).id("" + (i + 1)));
    }
    BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    System.out.println(bulk.hasFailures()); //是否失败
}

2 ES查询

2.1 ElasticSearch准备工作

  • 索引 : sms-logs-index
  • 类型:sms-logs-type
字段名称 备注
createDate 创建时间String
sendDate 发送时间 date
longCode 发送长号码 如 16092389287811 string
Mobile 如 13000000000
corpName 发送公司名称,需要分词检索
smsContent 下发短信内容,需要分词检索
State 短信下发状态 0 成功 1 失败 integer
Operatorid 运营商编号1移动2联通3电信 integer
Province 省份
ipAddr 下发服务器IP地址
replyTotal 短信状态报告返回时长 integer
Fee 扣费 integer
  • 创建实例代码

    //先定义索引名和类型名 
    String index = "sms_logs_index";
    String type = "sms_logs_type";
     @Autowired
        @Qualifier("restHighLevelClient")
        private RestHighLevelClient client;
    
        @Test
        public void create_index() throws IOException {
            CreateIndexRequest request = new CreateIndexRequest(index);
            XContentBuilder builder = XContentFactory.jsonBuilder();
            builder.startObject();
            {
                builder.startObject("properties");
                {
                    builder.startObject("createDate");
                    {
                        builder.field("type", "text");
                    }
                    builder.endObject();
                    builder.startObject("sendDate");
                    {
                        builder.field("type", "date")
                                .field("format", "yyyy-MM-dd");
                    }
                    builder.endObject();
                    builder.startObject("mobile");
                    {
                        builder.field("type", "text");
                    }
                    builder.endObject();
                    builder.startObject("corpName");
                    {
                        builder.field("type", "text")
                                .field("analyzer", "ik_max_word");
                    }
                    builder.endObject();
                    builder.startObject("smsContent");
                    {
                        builder.field("type", "text")
                        .field("analyzer","ik_max_word");
                    }
                    builder.endObject();
                    builder.startObject("state");
                    {
                        builder.field("type", "integer");
                    }
                    builder.endObject();
                    builder.startObject("operatorid");
                    {
                        builder.field("type", "integer");
                    }
                    builder.endObject();
                    builder.startObject("province");
                    {
                        builder.field("type", "text");
                    }
                    builder.endObject();
                    builder.startObject("ipAddr");
                    {
                        builder.field("type", "text");
                    }
                  builder.endObject();
                    builder.startObject("replyTotal");
                  {
                        builder.field("type", "integer");
                    }
                    builder.endObject();
                    builder.startObject("fee");
                    {
                        builder.field("type", "integer");
                    }
                    builder.endObject();
                }
                builder.endObject();
            }
            builder.endObject();
            request.mapping(builder);
            CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
            System.out.println(response);
        }
    • 数据导入部分

      PUT /sms_logs_index/_doc/1
      {
        "corpName": "途虎养车",
        "createDate": "2020-01-22",
        "fee": 3,
        "ipAddr": "10.123.98.0",
        "longCode": 106900000009,
        "mobile": "1738989222222",
        "operatorid": 1,
        "province": "河北",
        "relyTotal": 10,
        "sendDate": "2020-02-22",
        "smsContext":   "【途虎养车】亲爱的灯先生,您的爱车已经购买",
        "state": 0
      }

1 term&terms查询

1.1 term查询

  • ==term的查询是代表完全匹配,搜索之前不会对你的关键字进行分词==

    
    POST /sms_logs_index/_search
    {
      "query": {
        "term": {
          "province": [
            "京",
          ]
        }
      }
    }
    @Test
    public void termQuery() throws IOException {
        //请求对象
        SearchRequest request = new SearchRequest(index);
        //条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.from(0);
        builder.size(100);
        TermQueryBuilder query = QueryBuilders.termQuery("province", "河北");
        builder.query(query);
        request.source(builder);
    
        //执行查询
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //获取想要的数据
        SearchHits hits = search.getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            System.out.println("===="+source+"====");
        }
    }
    ##不会对term中所匹配的值进行分词查询

1.2 terms查询

  • 是针对一个字段包含多个值得运用

    
    POST /sms_logs_index/_search
    {
      "query": {
        "terms": {
          "province": [
            "京",
            "hebei"
          ]
        }
      }
    }
    @Test
    public void termsQuery() throws IOException {
        //请求对象
        SearchRequest request = new SearchRequest(index);
        //条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermsQueryBuilder query = QueryBuilders.termsQuery("province", "he", "bei","hebei");
        builder.query(query);
        request.source(builder);
    
        //执行查询
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //获取想要的数据
        SearchHits hits = search.getHits();
        for (SearchHit hit : hits) {
            Map<String, Object> source = hit.getSourceAsMap();
            System.out.println("===="+source+"====");
        }
    }

2 match查询

match查询属于高层查询,它会根据你查询字段类型不一样,采用不同的查询方式

match查询,实际底层就是多个term查询,将多个term查询的结果进行了封装

  • 查询的如果是日期或者是数值的话,它会根据你的字符串查询内容转换为日期或者是数值对等
  • 如果查询的内容是一个不可被分的内容(keyword),match查询不会对你的查询的关键字进行分词
  • 如果查询的内容是一个可被分的内容(text),match则会根据指定的查询内容按照一定的分词规则去分词进行查询0

2.1match_all查询


POST /sms_logs_index/_search
{
  "query": {
    "match_all": {}
  }
}
@Test
public void match_all() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    MatchAllQueryBuilder query = QueryBuilders.matchAllQuery();
    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        Map<String, Object> map = hit.getSourceAsMap();
        System.out.println(map);
    }
}
//只展示10条,默认

2.2match

POST /sms_logs_index/_search
{
  "query": {
    "match": {
      "province": "北京"
    }
  }
}

@Test
public void match() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    MatchQueryBuilder query = QueryBuilders.matchQuery("province","北京");
    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        Map<String, Object> map = hit.getSourceAsMap();
        System.out.println(map);
    }
    System.out.println(hits.getHits().length);
}

2.3.boolmatch

==可以用and 和 or连接==

POST /sms_logs_index/_search
{
  "query": {
    "match": {
      "province": {
        "query": "北 京",
        "operator": "and"
      }
    }
  }
}
POST /sms_logs_index/_search
{
  "query": {
    "match": {
      "province": {
        "query": "北 hebei",
        "operator": "or"
      }
    }
  }
}
@Test
public void boolQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    MatchQueryBuilder query = QueryBuilders.matchQuery("province","京 hebei").operator(Operator.OR);
    //        MatchQueryBuilder query = QueryBuilders.matchQuery("province","京 hebei").operator(Operator.AND);
    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        Map<String, Object> map = hit.getSourceAsMap();
        System.out.println(map);
    }
    System.out.println(hits.getHits().length);
}

2.4 multi_match

==针对多个key 进行查询,多个key对于多个value==


POST /sms_logs_index/_search
{
  "query": {
    "multi_match": {
      "query": "京 爱",
      "fields": ["province","smsContent","smsContext"]
    }
  }
}
@Test
public void multiMatchQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery("京 爱", "province", "smsContent", "smsContext");
    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    SearchHits hits = response.getHits();
    for (SearchHit hit : hits) {
        Map<String, Object> map = hit.getSourceAsMap();
        System.out.println(map);
    }
    System.out.println(hits.getHits().length);
}

3.其他查询

3.1 ID查询

GET /sms_logs_index/_doc/1


@Test
public void QueryById() throws IOException {
    GetRequest request = new GetRequest(index);
    request.id("1");
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    System.out.println(response.getSourceAsMap());
}

3.2 多个ID查询

POST /sms_logs_index/_search
{
  "query": {
    "ids": {
      "values": ["1","2"]
    }
  }
}

@Test
public void IDS() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    IdsQueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "2", "3");
    builder.query(queryBuilder);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()) {
        Map<String, Object> map = hit.getSourceAsMap();
        System.out.println(map);
    }

}

3.3 prefix

POST /sms_logs_index/_search
{
  "query": {
    "prefix": {
      "corpName": {
        "value": "花"
      }
    }
  }
}
@Test
public void prefixQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    PrefixQueryBuilder query = QueryBuilders.prefixQuery("corpName", "花钱");
    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

模糊查询,输入字符大概,直接去查询

3.4 fuzzy

POST /sms_logs_index/_search
{
  "query": {
    "fuzzy": {
      "smsContext": {
        "value": "车",
        "prefix_length": 1
      }
    }
  }
}
@Test
public void fuzzy() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.fuzzyQuery("corpName","花钱").prefixLength(1));  //可指定前面多少个必须正确与
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

3.5.wildcard查询

通配查询

POST /sms_logs_index/_search
{
  "query": {
    "wildcard": {
      "corpName": {
        "value": "中国*"
      }
    }
  }
}
POST /sms_logs_index/_search
{
  "query": {
    "wildcard": {
      "corpName": {
        "value": "中国*"
      }
    }
  }
}
@Test
public void wildcard() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.wildcardQuery("corpName","中国"));
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

3.6 范围查询range

POST /sms_logs_index/_search
{
  "query": {
    "range": {
      "fee": {
        "gte": 0,
        "lte": 999
      }
    }
  }
}

@Test
public void rangeQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.rangeQuery("fee").gte(0).lte(9999));
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

3.7 正则查询


POST /sms_logs_index/_search
{
  "query": {
    "regexp": {
      "mobile": "1[0-9].*"
    }
  }
}
@Test
public void regexpQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.regexpQuery("mobile","1[0-9].*"));
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

3.8 深分页Scroll

==from和size 的和超过1w的时候,效率非常的慢==

原理:

from+size  ES查询数据的方式:
     1  先将用户指定的关键词进行分词处理
    2  将分词去词库中进行检索,得到多个文档的id
    3  去各个分片中拉去指定的数据   耗时
    4  根据数据的得分进行排序       耗时
    5  根据from的值,将查询到的数据舍弃一部分,
    6  返回查询结果

Scroll+size    在ES中查询方式
    1  先将用户指定的关键词进行分词处理
    2  将分词去词库中进行检索,得到多个文档的id
    3  将文档的id存放在一个ES的上下文中,ES内存
    4  根据你指定给的size的个数去ES中检索指定个数的数据,拿完数据的文档id,会从上下文中移除
    5  如果需要下一页的数据,直接去ES的上下文中,找后续内容
    6  循环进行4.5操作

缺点,Scroll是从内存中去拿去数据的,不适合做实时的查询,拿到的数据不是最新的

# 执行scroll查询,返回第一页数据,并且将文档id信息存放在ES的上下文中,指定生存时间
POST /sms_logs_index/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "sort": [
    {
      "fee": {
        "order": "desc"
      }
    }
  ]
}

#根据Scroll查询第二页的数据
POST /_search/scroll
{
  "scroll_id":
  "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHpvZWRhWFlCd2F4Z2pkZHBHR0NrAAAAAAAAAZIWUXZnemxCZWtUenlxOXZQdEQ4QlVPQQ==",
  "scroll":"1m"
}

# 删除scroll数据
DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHpvZWRhWFlCd2F4Z2pkZHBHR0NrAAAAAAAAAZIWUXZnemxCZWtUenlxOXZQdEQ4QlVPQQ==
    @Test
    public void ScrollQuery() throws IOException {
        //        1   创建SearchRequest
        SearchRequest request = new SearchRequest(index);
//        2   指定scroll信息,生存时间
        request.scroll(TimeValue.timeValueMinutes(1L));
//        3   指定查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(2);
        builder.sort("fee", SortOrder.DESC);
        builder.query(QueryBuilders.matchAllQuery());
//        4 获取返回结果scrollid ,source
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        String scrollId = response.getScrollId();
        System.out.println(scrollId);
        while (true) {
//       5  循环创建SearchScrollRequest
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            // 6 指定scrollid生存时间
            scrollRequest.scroll(TimeValue.timeValueMinutes(1L));
//        7 执行查询获取返回结果
            SearchResponse scrollResp = client.scroll(scrollRequest, RequestOptions.DEFAULT);
//        8.判断是否得到数据,输出
            if (scrollResp.getHits().getHits() != null && scrollResp.getHits().getHits().length > 0) {
                System.out.println("=======下一页的数据========");
                for (SearchHit hit : scrollResp.getHits().getHits()) {
                    System.out.println(hit.getSourceAsMap());
                }
            } else {
                //        9。判断没有查询到数据-退出循环
                System.out.println("没得");
                break;
            }
        }
        // 10  创建clearScrollRequest
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        // 11 指定scrollid
        clearScrollRequest.addScrollId(scrollId);
        // 12  删除
        client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
    }

3.7 delete-by-query

根据term,match等查询方式去删除大量的文档

如果你需要删除的内容,是index下的大部分数据,不建议使用,建议逆向操作,创建新的索引,添加需要保留的数据内容

POST /sms_logs_index/_delete_by_query
{
  "query": {
    "ids": {
      "values": ["1","2"]
    }
  }
}
@Test
public void deleteQuery() throws IOException {
    DeleteByQueryRequest request = new DeleteByQueryRequest(index);
    request.setQuery(QueryBuilders.idsQuery().addIds("1","2"));
    BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);
    System.out.println(response.toString());
}

3.复合查询

3.1 ==bool查询==

复合过滤器,可以将多个查询条件以一定的逻辑组合在一起,and or

  • must : 所有的条件,用must组合在一起,表示AND
  • must_not:将must_not中的条件,全部不能匹配,表示not的意思,不能匹配该查询条件
  • should: 所有条件,用should组合在一起,表示or的意思,文档必须匹配一个或者多个查询条件
  • filter: 过滤器,文档必须匹配该过滤条件,跟must子句的唯一区别是,filter不影响查询的score
POST /sms_logs_index/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "province": {
              "value": "四川"
            }
          }
        },
        {
          "term": {
            "corpName": {
              "value": "中国"
            }
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "operatorid": {
              "value": "2"
            }
          }
        }
      ],
      "must": [
        {
          "term": {
            "smsContext": {
              "value": "都"
            }
          }
        }
      ]
    }
  }
}
@Test
public void BoolQuery() throws IOException {
    SearchRequest request = new SearchRequest(index);

    SearchSourceBuilder builder = new SearchSourceBuilder();
    BoolQueryBuilder query = QueryBuilders.boolQuery();
    query.should(QueryBuilders.termQuery("province","四川"));
    query.should(QueryBuilders.termQuery("corpName","中国"));
    query.mustNot(QueryBuilders.termQuery("operatorid","2"));
    query.must(QueryBuilders.termQuery("smsContext","都"));


    builder.query(query);
    request.source(builder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }

}

3.2 booting查询

boosting 查询可以帮助我们去影响查询后的score
positive:只有匹配上positive 查询的内容,才会被放到返回的结果集中
negative: 如果匹配上了positive 也匹配上了negative, 就可以 降低这样的文档score.
negative_boost:指定系数,必须小于1 0.5
关于查询时,分数时如何计算的:
搜索的关键字再文档中出现的频次越高,分数越高
指定的文档内容越短,分数越高。
我们再搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数就越高。

#boosting 查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "smsContent": "战士"
        }
      }, 
      "negative": {
        "match": {
          "smsContent": "团队"
        }
      },
      "negative_boost": 0.2
    }
  }
}
public void  boolSearch() throws IOException {

        //  1.创建 searchRequest
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        // 2.指定查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // #省是 晋城 或者北京
        boolQueryBuilder.should(QueryBuilders.termQuery("province","北京"));
        boolQueryBuilder.should(QueryBuilders.termQuery("province","晋城"));

        //# 运营商不能是联通
        boolQueryBuilder.mustNot(QueryBuilders.termQuery("operatorId",2));

        //#smsContent 包含 战士 和的
        boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","战士"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","的"));

        builder.query(boolQueryBuilder);
        request.source(builder);
        //  3.执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.输出结果
        for (SearchHit hit : response.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
    }

3.3 filter 查询

query 查询:根据你的查询条件,去计算文档的匹配度得到一个分数,并根据分数排序,不会做缓存的。

filter 查询:根据查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存

#filter 查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "corpName": "海尔智家公司"
           }
        },
        {
          "range":{
            "fee":{
              "lte":50
            }
          }
        }
      ]
    }
  }
}
public void  boostSearch() throws IOException {

    //  1.创建 searchRequest
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    // 2.指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    BoostingQueryBuilder boost = QueryBuilders.boostingQuery(
        QueryBuilders.matchQuery("smsContent", "战士"),
        QueryBuilders.matchQuery("smsContent", "团队")
    ).negativeBoost(0.2f);
    builder.query(boost);
    request.source(builder);
    //  3.执行查询
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.输出结果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

3.4 高亮查询

高亮查询就是用户输入的关键字,以一定特殊样式展示给用户,让用户知道为什么这个结果被检索出来
高亮展示的数据,本身就是文档中的一个field,单独将field以highlight的形式返回给用户
ES提供了一个highlight 属性,他和query 同级别。
 frament_size: 指定高亮数据展示多少个字符回来
 pre_tags:指定前缀标签<front color="red">
 post_tags:指定后缀标签 </font>
#highlight 高亮查询
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match": {
      "smsContent": "团队"
    }
  },
  "highlight": {
    "fields": {
      "smsContent":{}
    },
    "pre_tags":"<font color='red'>",
    "post_tags":"</font>",
    "fragment_size":10
  }
}
public void filter() throws IOException {

    // 1.searchRequest
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.types(type);

    // 2.指定查询条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
    boolBuilder.filter(QueryBuilders.termQuery("corpName","海尔智家公司"));
    boolBuilder.filter(QueryBuilders.rangeQuery("fee").gt(20));
    sourceBuilder.query(boolBuilder);
    searchRequest.source(sourceBuilder);

    //  3.执行
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

    //  4. 输出结果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
        System.out.println(hit.getId()+"的分数是:"+hit.getScore());
    }
}

3.5 聚合查询

ES的聚合查询和mysql 的聚合查询类似,ES的聚合查询相比mysql 要强大得多。ES提供的统计数据的方式多种多样。
#ES 聚合查询的RSTFul 语法
POST /index/type/_search
{
    "aggs":{
        "(名字)agg":{
            "agg_type":{
                "属性""值"
            }
        }
    }
}
 public void highLightQuery() throws IOException {
      // 1.创建request
        SearchRequest request = new SearchRequest(index);

      // 2.指定查询条件,指定高亮
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchQuery("smsContent","团队"));
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("smsContent",10)
                .preTags("<font colr='red'>")
                .postTags("</font>");
        builder.highlighter(highlightBuilder);
        request.source(builder);

      // 3.执行
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4. 输出结果
        for (SearchHit hit : response.getHits().getHits()) {
            System.out.println(hit.getHighlightFields().get("smsContent"));
        }
    }

3.5.1 去重计数

去重计数,cardinality 先将返回的文档中的一个指定的field进行去重,统计一共有多少条
# 去重计数 查询 province
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "provinceAgg": {
      "cardinality": {
        "field": "province"
      }
    }
  }
}
public void aggCardinalityC() throws IOException {

    // 1.创建request
    SearchRequest request = new SearchRequest(index);

    // 2. 指定使用聚合查询方式
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.aggregation(AggregationBuilders.cardinality("provinceAgg").field("province"));
    request.source(builder);

    // 3.执行查询
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    // 4.输出返回结果
    Cardinality agg = response.getAggregations().get("provinceAgg");
    System.out.println(agg.getValue());
}

3.5.2 范围统计

统计一定范围内出现的文档个数,比如,针对某一个field 的值再0~100,100~200,200~300 之间文档出现的个数分别是多少
范围统计 可以针对 普通的数值,针对时间类型,针对ip类型都可以响应。
数值 rang    
时间  date_rang     
ip   ip_rang
#针对数值方式的范围统计  from 带等于效果 ,to 不带等于效果
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "range": {
        "field": "fee",
        "ranges": [
          {
            "to": 30
          },
           {
            "from": 30,
            "to": 60
          },
          {
            "from": 60
          }
        ]
      }
    }
  }
}
#时间方式统计
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "date_range": {
        "field": "sendDate",
        "format": "yyyy", 
        "ranges": [
          {
            "to": "2000"
          },{
            "from": "2000"
          }
        ]
      }
    }
  }
}
#ip 方式 范围统计
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "ip_range": {
        "field": "ipAddr",
        "ranges": [
          {
            "to": "127.0.0.8"
          },
          {
            "from": "127.0.0.8"
          }
        ]
      }
    }
  }
}
 public void aggRang() throws IOException {
        // 1.创建request
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        // 2. 指定使用聚合查询方式
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.aggregation(AggregationBuilders.range("agg").field("fee")
                            .addUnboundedTo(30)
                            .addRange(30,60)
                            .addUnboundedFrom(60));
        request.source(builder);

        // 3.执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.输出返回结果
        Range agg = response.getAggregations().get("agg");
        for (Range.Bucket bucket : agg.getBuckets()) {
            String key = bucket.getKeyAsString();
            Object from = bucket.getFrom();
            Object to = bucket.getTo();
            long docCount = bucket.getDocCount();
            System.out.println(String.format("key: %s ,from: %s ,to: %s ,docCount: %s",key,from,to,docCount));
        }
    }

3.5.3 统计查询

他可以帮你查询指定field 的最大值,最小值,平均值,平方和...
使用 extended_stats
#统计聚合查询 extended_stats
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "extended_stats": {
        "field": "fee"
      }
    }
  }
}
// java实现   
public void aggExtendedStats() throws IOException {
        // 1.创建request
        SearchRequest request = new SearchRequest(index);
        request.types(type);

        // 2. 指定使用聚合查询方式
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.aggregation(AggregationBuilders.extendedStats("agg").field("fee"));
        request.source(builder);

        // 3.执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.输出返回结果
       ExtendedStats extendedStats =  response.getAggregations().get("agg");
        System.out.println("最大值:"+extendedStats.getMaxAsString()+",最小值:"+extendedStats.getMinAsString());
    }

3.5.4 分类查询(应用)


GET article_nested/_search
{
  "size": 0, 
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "dataflag": {
              "value": "1"
            }
          }
        },
        {
          "constant_score": {
            "filter": {
              "range": {
                "pubtime": {
                  "gte": "2021-03-22 00:00:00",
                  "lte": "2021-03-22 23:59:59"
                }
              }
            },
            "boost": 1.2
          }
        }
      ]
    }
  },
    "aggs":{
    "web_url":{
      "terms": {
        "field": "websiteZh"
      }
    }
  }
}

-------------------------------------------------------------------------------------------------------


    private void getWebSiteCategoryToday(RealTimeNewCategory realTimeNewCategory, List<RealTimeNewCategoryVo> vos) {

        SearchRequest searchRequest = new SearchRequest(KdConstant.ELASTICSEARCH.ESALIAS);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.size(0);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("dataflag", realTimeNewCategory.getSource()));
        String format = getCurrentTime();
        boolQueryBuilder.must(QueryBuilders.rangeQuery(Constant.PUBTIME).from(format + " 00:00:00").to(format + " 23:59:59"));
        builder.query(boolQueryBuilder);

        builder.aggregation(AggregationBuilders.terms("web_url").field("websiteZh"));
        searchRequest.source(builder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (KdUtil.isNotEmpty(searchResponse)) {
            Terms terms = searchResponse.getAggregations().get("web_url");
            HashMap<String, Long> map = new HashMap<>(KdUtil.getTableSize(vos.toArray().length));
            for (Terms.Bucket bucket : terms.getBuckets()) {
                map.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
            for (RealTimeNewCategoryVo vo : vos) {
                vo.setToday(map.getOrDefault(vo.getWebsiteZh(), 0L));
            }
        }
    }

文章作者: anlen123
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 anlen123 !
 上一篇
docker教程 docker教程
docker教程1. Docker(一):Docker安装与底层原理 镜像(image):Docker镜像就相当于是一个文件系统,通俗来说就是为容器用来创建容器的 容器(Container):Docker 利用容器 (Container)
2020-12-24 anlen123
下一篇 
Java-Feature Java-Feature
Java Featurepackage com.lhq.Main; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.Feature; import
2020-12-24 anlen123
  目录