ES6.8.6 Java客户端发起 增删改查 query (bool)、update、delete

news2024/11/15 5:04:28

文章目录

    • 环境
    • 测试数据
      • 单个新增
      • 批量新增
      • 通过`delete by api`删除
      • 通过`delete by query api`删除
      • 删除索引中指定字段(script)
      • 单个修改`update by api`
      • 通过`_bulk`批量修改
      • 批量修改`update by query api`
      • 使用script脚本修改
      • 完全匹配(term)
      • 分词(match)
      • 分词(match_phrase)
      • is null、空白字符
      • 不为null,不是空白字符
      • 通配符(?、*)
      • 排序(sort)
      • 范围查询(rangeQuery)
      • must、should、filter
      • 更多查询:待补充...
    • 异常

环境

  • elasticsearch6.8.6版本:已安装ik分词器、icu分词器、pinyin分词器(分词器版本要和es版本一致)

测试数据

测试数据使用配置了ik分词器的索引:ik_news
初始化测试数据,在测试过程中可能发生修改、新增或删除。
image.png

单个新增


    @Autowired
    private ElasticsearchRestTemplate restTemplate;
	
	/*

        ==================================
        https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs.html
        官网提供了java 操作api教程
     */
    @Test
    public void addOrUpdateOne() {

        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        // 模拟插入的数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("id", 12);
        dataMap.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
        dataMap.put("uv", 500);
        dataMap.put("create_date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        dataMap.put("status", 1);
        dataMap.put("remark", "来源博客园");

        // 更新请求
        UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(dataMap, "id"));
        // 需要更新或插入的数据
        updateRequest.doc(dataMap);
        // 更新目标存在更新,不存在新增,如果不设置在找不到_id对应值的时候,直接报错
        updateRequest.docAsUpsert(true);

        try {
            UpdateResponse updateResponse = restTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
            // 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
            // restTemplate.refresh(index);
            System.out.println(updateResponse);
        } catch (Exception e) {
            System.out.println("ES数据更新失败:" + e.getMessage());
        }
    }

批量新增

create_date: 字段原写错为:create_data,后来发现更正,见【删–>删除索引中指定字段】目录删除错误的字段写入。




    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    /*
        https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-bulk.html
        官网提供:批量更新示例
     */
    @Test
    public void addOrUpdateBatch() throws IOException {

        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        List<Map<String, Object>> dataList = new ArrayList<>();
        // 模拟批量更新数据
    	// create_date: 字段原写错为:create_data,后来发现更正【见删--删除索引中指定字段】删除错误的写入。
        Map<String, Object> dataMap1 = new HashMap<>();
        dataMap1.put("id", 13);
        dataMap1.put("title", "Es 超时设置 high-level-client_es highlevelclient-CSDN博客");
        dataMap1.put("uv", 200);
        dataMap1.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        dataMap1.put("status", 1);
        dataMap1.put("remark", "来源CSDN博客");

        Map<String, Object> dataMap2 = new HashMap<>();
        dataMap2.put("id", 14);
        dataMap2.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
        dataMap2.put("uv", 259);
        dataMap2.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        dataMap2.put("status", 1);
        dataMap2.put("remark", "来源博客园");

        dataList.add(dataMap1);
        dataList.add(dataMap2);

        BulkRequest bulkRequest = new BulkRequest(index, type);

        for (Map<String, Object> map : dataList) {

            UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(map, "id"));
            updateRequest.doc(map);
            updateRequest.docAsUpsert(true);
            // 加入批量
            bulkRequest.add(updateRequest);
        }

        try {
            BulkResponse bulkResponse = restTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);

            // 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
            // restTemplate.refresh(index);
            System.out.println(bulkResponse);
        } catch (Exception e) {
            System.out.println("ES数据批量更新失败:" + e.getMessage());
        }
    }

通过delete by api删除

删除_id=8的记录

    @Autowired
    private ElasticsearchRestTemplate restTemplate;


	@Test
    public void deleteOne() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        long id = 8L;

        DeleteRequest deleteRequest = new DeleteRequest(index, type, Long.toString(id));

        try {
            DeleteResponse response = restTemplate.getClient().delete(deleteRequest, RequestOptions.DEFAULT);

            System.err.println(response.getResult());
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("删除记录失败!");
        }

    }

通过delete by query api删除

删除create_date值为null或者空字符。

条件删除一定要慎重使用,一旦查询的字段名写错,造成全查询,那就game over了。

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 通过查询条件删除
     */
    @Test
    public void deleteByQuery() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index);

        deleteByQueryRequest.setBatchSize(100);
        deleteByQueryRequest.setDocTypes(type);
        deleteByQueryRequest.setRefresh(true);

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 判断create_date为null
        boolQuery.mustNot(QueryBuilders.existsQuery("create_date"));
        deleteByQueryRequest.setQuery(boolQuery);


        try {
            restTemplate.getClient().deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("批量删除失败!");
        }


    }

删除索引中指定字段(script)

如果在添加数据的时候,字段名写错了,需要在当前索引中删除指定字段。

image.png
java客户端请求:删除索引中字段名create_data

	
    @Autowired
    private ElasticsearchRestTemplate restTemplate;

	/*
        删除索引中指定的字段
        https://www.cnblogs.com/8765h/p/17318622.html
        //
        https://blog.csdn.net/weixin_43823808/article/details/119930308
        //
        https://www.yisu.com/ask/28519983.html
     */
    @Test
    public void deleteField() throws IOException {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        /*

            mapping数据结构:
                {
                    "properties": {
                        "field_1": {
                            "type": "keyword",
                            "fields": {
                                "keyword": {
                                    ...
                                }
                            }
                        }
                    }
                }
         */

        // 需要移除的字段
        String[] filedNames = {"create_data"};


        // 获取索引中已经存在的索引
        Map<String, Object> mapping = restTemplate.getMapping(index, type);
        Map properties = MapUtil.get(mapping, "properties", Map.class);


        for (Object o : properties.keySet()) {
            // key:索引中字段名
            String key = o.toString();

            // 判断需要删除的字段,是否在索引中,如果在当前索引中,删除
            if (Arrays.stream(filedNames).collect(Collectors.toList()).contains(key)) {
                UpdateByQueryRequest request = new UpdateByQueryRequest(index);
                // 匹配文档中所有数据,需要一条一条做更新
                request.setQuery(QueryBuilders.matchAllQuery());
                // 把字段设置为null
                // request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source." + key + " = null", new HashMap<>()));
                // 使用remove直接把字段移除
                request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.remove('" + key + "')", new HashMap<>()));
                request.setBatchSize(1000);
                request.setRefresh(true);
                try {
                    BulkByScrollResponse bulkByScrollResponse = restTemplate.getClient().updateByQuery(request, RequestOptions.DEFAULT);

                } catch (IOException e) {
                    System.err.println("删除字段错误");
                }
            }
        }
    }


单个修改update by api


    @Test
    public void updateOne() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        // 模拟修改的数据
        // 不需要修改的字段不要写在这里,仅会对指定字段更新
        Map<String, Object> dataMap = new HashMap<>();
        // id找不到的记录会报错:
        // Elasticsearch exception [type=document_missing_exception, reason=[_doc][122]: document missing]
        dataMap.put("id", 12);
        dataMap.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟");
        dataMap.put("uv", 520);
        dataMap.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        // 写错的字段会插入到记录里面
        // dataMap.put("create_data", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

        // 更新请求
        UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(dataMap, "id"));
        // 需要更新或插入的数据
        updateRequest.doc(dataMap);
        // 更新目标存在更新,不存在新增,在只允许修改的情况下这一段一定要注释掉。注释后如果修改的记录不存在会报错.
        // updateRequest.docAsUpsert(true);

        try {
            UpdateResponse updateResponse = restTemplate.getClient().update(updateRequest, RequestOptions.DEFAULT);
            // 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
            // restTemplate.refresh(index);
            System.out.println(updateResponse);
        } catch (Exception e) {
            System.out.println("ES数据更新失败:" + e.getMessage());
        }
    }

通过_bulk批量修改

    @Test
    public void updateBatch() throws IOException {

        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        List<Map<String, Object>> dataList = new ArrayList<>();
        // 模拟更新数据
        Map<String, Object> dataMap1 = new HashMap<>();
        dataMap1.put("id", 13);
        dataMap1.put("title", "Es 超时设置 high-level-client_es highlevelclient-CSDN博客");
        dataMap1.put("uv", 200);
        dataMap1.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        dataMap1.put("status", 1);
        dataMap1.put("remark", "来源CSDN博客");

        Map<String, Object> dataMap2 = new HashMap<>();
        dataMap2.put("id", 14);
        dataMap2.put("title", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园");
        dataMap2.put("uv", 259);
        dataMap2.put("create_date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        dataMap2.put("status", null); // 设置为null
        dataMap2.put("remark", null); // 设置为null

        dataList.add(dataMap1);
        dataList.add(dataMap2);

        BulkRequest bulkRequest = new BulkRequest(index, type);

        for (Map<String, Object> map : dataList) {

            UpdateRequest updateRequest = new UpdateRequest(index, type, MapUtil.getStr(map, "id"));
            updateRequest.doc(map);
            // 更新目标存在更新,不存在新增,在只允许修改的情况下这一段一定要注释掉。注释后如果修改的记录不存在会报错.
            // updateRequest.docAsUpsert(true);
            // 加入批量
            bulkRequest.add(updateRequest);
        }

        try {
            BulkResponse bulkResponse = restTemplate.getClient().bulk(bulkRequest, RequestOptions.DEFAULT);

            // 更新后数据从内存刷新到磁盘,实时刷新可能会影响性能
            // restTemplate.refresh(index);
            System.out.println(bulkResponse);
        } catch (Exception e) {
            System.out.println("ES数据批量更新失败:" + e.getMessage());
        }
    }

批量修改update by query api

【ES官网:无法对 null 值进行索引或搜索。当字段设置为 null (或空数组或值数组)时,该字段将被视为没有 null 值。】

【ES官网:由于各种原因,文档字段的索引值可能不存在】

需要注意的是,如果字段值设置为显示的null(空数组也不会被索引),那这个字段不会被es索引,所以通过某个字段=null是查不到数据的,但是可以在创建索引的时候指定null_value=NULL进行替换:

{
    "settings": {
        "analysis": {
            "analyzer": {
                "default": {
                    "type": "ik_max_word"
                }
            }
        }
    },
    "mapping": {
        "_doc": {
            "properties": {
                // null_value设置示例
                "create_date": {
                    "type": "date",
                    "null_value": "NULL"
                }
            }
        }
    }
}

由于索引中未设置null_value替换,所以不能查询null的值去更新了。


    @Test
    public void updateByQuery() {

        // 把所有status存在的数据时间和status进行更新

        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest(index);
        updateByQueryRequest.setDocTypes(type);
        updateByQueryRequest.setRefresh(true);
        updateByQueryRequest.setBatchSize(100);

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.existsQuery("status"));

        updateByQueryRequest.setQuery(boolQuery);
        // 需要更新的数据
        updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.create_date = " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "", new HashMap<>()));
        updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.status = 2", new HashMap<>()));

        try {
            BulkByScrollResponse updatedByQuery = restTemplate.getClient().updateByQuery(updateByQueryRequest, RequestOptions.DEFAULT);

            System.out.println(updatedByQuery);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

使用script脚本修改

注!使用条件查询进行更新或者删除一定要慎重,因为一旦条件写错可能会造成全查询,数据更新错误或者删除错误。


    /**
     * 通过脚本更新数据
     */
    @Test
    public void updateByScript() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        UpdateByQueryRequest request = new UpdateByQueryRequest(index);
        // 匹配文档中所有数据,需要一条一条做更新
        // 把ID为11的数据,时间更新为null,状态更新为null
        request.setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("id", 11)));
        // 把字段设置为null
        request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.create_date = null", new HashMap<>()));
        request.setScript(new Script(ScriptType.INLINE, "painless", "ctx._source.status = null", new HashMap<>()));
        request.setBatchSize(1000);
        request.setDocTypes(type);
        request.setRefresh(true);
        try {
            BulkByScrollResponse bulkByScrollResponse = restTemplate.getClient().updateByQuery(request, RequestOptions.DEFAULT);

            System.out.println("更新:" + bulkByScrollResponse.getUpdated());
        } catch (IOException e) {
            System.err.println("更新字段错误!");
        }
    }

完全匹配(term)


    /**
     * 完全匹配查询: term进行更精准的查询匹配
     */
    @Test
    public void selectByBoolQueryTerm() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // text类型的字段,要term查询需要加上“.keyword”
        sourceBuilder.query(boolQuery.must(QueryBuilders.termQuery("title.keyword", "ES客户端请求超时问题排查 - 爱定小闹钟 - 博客园")));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

分词(match)


    @Test
    public void selectByBoolQueryMatch() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 匹配所有包含:“三毛”、“三”、“毛”的数据
        sourceBuilder.query(boolQuery.must(QueryBuilders.matchQuery("title", "三毛")));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

分词(match_phrase)

matchmatch_phrase有什么区别?
match_phrase可以指定分词匹配的间隔,比match匹配更严格一些。


    @Test
    public void selectByBoolQueryMatchPhrase() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 匹配所有包含:连续在一起的“三毛”的数据
        // slop指定的是分词匹配的间隔,0,代表无间隔,只能匹配到包含连续“三毛”的数据
        // 匹配方式比match更严格
        sourceBuilder.query(boolQuery.must(QueryBuilders.matchPhraseQuery("title", "三毛").slop(0)));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

is null、空白字符

更新的数据见【改–>使用script脚本修改】目录。

无法查询到索引数据(null,[]无法被索引)见【改–>批量修改update by query api】目录。


    /**
     * 布尔查询
     */
    @Test
    public void selectByBoolQuery() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 查询 create_date = 空
        sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("create_date")));
        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

不为null,不是空白字符

    /**
     * 布尔查询
     */
    @Test
    public void selectByBoolQuery2() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 查询 create_date is not null and status is not null
        sourceBuilder.query(boolQuery.must(QueryBuilders.existsQuery("create_date")));
        sourceBuilder.query(boolQuery.must(QueryBuilders.existsQuery("status")));

//        sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("create_date")));
//        sourceBuilder.query(boolQuery.mustNot(QueryBuilders.existsQuery("status")));
        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

通配符(?、*)

    @Test
    public void selectByBoolQuery3() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 参考关于通配符的使用:https://blog.csdn.net/HiBoyljw/article/details/90747211
        // 不加".keyword",会给分词,所以查不到结果了。
        sourceBuilder.query(boolQuery.must(QueryBuilders.wildcardQuery("title.keyword", "*天才作家*")));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

排序(sort)


    @Test
    public void selectByBoolQueryMatchAllSort() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查询所有
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        // 多条件排序可以通过设置多个sort
        // 在时间升序的基础上,id升序
        // 按时间升序排序
        sourceBuilder.sort("create_date", SortOrder.ASC);
        // 按ID升序排序
        sourceBuilder.sort("id", SortOrder.ASC);

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

范围查询(rangeQuery)

    @Test
    public void selectByRangeQuery() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 范围查询 2024-01-22 <= time <= 2024-01-25
        sourceBuilder.query(QueryBuilders.rangeQuery("create_date").gte("2024-01-22").lte("2024-01-25"));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

查询结果打印:

{uv=131, remark=来源网易科技, id=9, title=网易公布2022年第三季度财报|净收入|毛利润, create_date=2024-01-22, status=2}
{uv=310, remark=来源新浪财经, id=10, title=单季盈利超100亿元!比亚迪三季度毛利率超特斯拉, create_date=2024-01-23, status=2}
{uv=200, remark=来源知乎搜索, id=6, title=超全整理!三毛最出名的11本著作,没读过的一定要看看, create_date=2024-01-23, status=2}

must、should、filter

【ES官网:查询和筛选上下文】
【ES官网:布尔查询】
【The minimum_should_match parameter possible values】

  1. must

            子句(查询)必须出现在匹配的文档中,并计入分数。

  2. should

            子句 (query) 应出现在匹配的文档中。如果查询位于 bool 查询上下文中并且具有 must or filter 子句,则即使所有查询都不匹配,文档也会与 bool should 查询匹配。在这种情况下,这些子句仅用于影响分数。如果查询位于筛选器上下文中,或者两者都没有 must , filter 则必须至少有一个查询与文档匹配,才能使 bool 文档与 bool should 查询匹配。可以通过设置 minimum_should_match 参数来显式控制此行为。

  3. filter

            子句(查询)必须出现在匹配的文档中。但是,与查询的分数不同的 must 是,查询将被忽略。筛选器子句在筛选器上下文中执行,这意味着将忽略评分,并考虑将子句用于缓存。

        三者聚合查询实例:

image.png

    @Test
    public void selectMustShouldFilter() {
        String index = "ik_news"; // 索引名
        String type = "_doc"; // 文档类型

        SearchRequest searchRequest = new SearchRequest();

        searchRequest.indices(index);
        searchRequest.types(type);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // must必须匹配status=2
        sourceBuilder.query(boolQuery.must(QueryBuilders.termQuery("status", 2))); // ok
        // should至少包含n个筛选条件, 需要指定参数minimum_should_match = n
        sourceBuilder.query(boolQuery.should(QueryBuilders.wildcardQuery("remark.keyword", "*百度*")));
        // 设置符合must后,至少还要包含一个能匹配到should条件的参数。如果不配置此参数,should条件将不生效,设置1是在must筛选之后再匹配一遍参数
        boolQuery.minimumShouldMatch(1);
        // filter: 过滤uv >= 150的数据
        sourceBuilder.query(boolQuery.filter(QueryBuilders.rangeQuery("uv").gte(150)));

        searchRequest.source(sourceBuilder);

        try {
            SearchResponse search = restTemplate.getClient().search(searchRequest, RequestOptions.DEFAULT);

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

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

查询结果:

{uv=300, remark=来源百度知道, id=7, title=三毛的英文名为什么叫Echo?, create_date=2024-01-21, status=2}

更多查询:待补充…

待补充…

异常

执行更新操作UpdateRequest:索引中存在记录更新,不存在记录新建。
java.net.SocketTimeoutException: 30,000 milliseconds timeout on connection http-outgoing-0 [ACTIVE]

image.png
解决方式:

  1. 配置连接超时时间大于30s:未解决

            这是从异常情况直观看到的,就是连接超时,但是具体因为什么超时的未知。
            配置超时时间,这也是网上大多数给到的答案,但是没有解决我的问题。

  2. 先查询记录,然后再修改:未解决

            同时看到网上说es有个bug,先查询,再修改就不会出现超时的错误,但是没有说的哪个版本的问题,我试了一下没有解决。

  3. 修改配置文件:问题解决

            因为我是在windows系统上做的测试,下载es之后就直接启动了,没有对配置文件elasticsearch.yml做任何配置。
            我用postman发起http请求做测试的时候,增删改查都是成功的。但是配置Java客户端发起请求就失败了!!

        Java配置:

spring:
  # es连接配置
  elasticsearch:
    rest:
      uris: 127.0.0.1:9200
      username:
      password:

        一般,单机上.yml需要修改几个内容:

cluster.name: master
node.name: node-1
path.data: /path/to/data
path.logs: /path/to/logs
network.host: 0.0.0.0
http.port: 9200

        修改之后,重启es,重新发起更新请求,成功了!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux:进程信号

文章目录 信号的概念实践信号关于前台和后台进程的操作 操作系统与外设信号的产生 前面的篇章结束了信号量的话题&#xff0c;那么接下来引入的是信号的话题&#xff0c;信号和信号量之间没有任何关系&#xff0c;只是名字比较像 信号的概念 在生活中存在各种各样的信号&…

【游戏服务器部署】幻兽帕鲁服务器一键部署保姆级教程,游戏私服还是自己搭建的香

在帕鲁的世界&#xff0c;你可以选择与神奇的生物「帕鲁」一同享受悠闲的生活&#xff0c;也可以投身于与偷猎者进行生死搏斗的冒险。帕鲁可以进行战斗、繁殖、协助你做农活&#xff0c;也可以为你在工厂工作。你也可以将它们进行售卖&#xff0c;或肢解后食用。—幻兽帕鲁 想要…

【Linux】压缩脚本、报警脚本

一、压缩搅拌 要求&#xff1a; 写一个脚本&#xff0c;完成如下功能 传递一个参数给脚本&#xff0c;此参数为gzip、bzip2或者xz三者之一&#xff1b; (1) 如果参数1的值为gzip&#xff0c;则使用tar和gzip归档压缩/etc目录至/backups目录中&#xff0c;并命名为/backups/etc…

【新书推荐】4.1节 数值编码规则

本节内容&#xff1a;不同进制数据的编码规则。 ■数值数据的编码规则&#xff1a;二进制数、十六进制数和十进制数&#xff0c;以及无符号整数和有符合整数的编码规则。 ■基本数据类型&#xff1a;编译器指定的数据类型为基本数据类型。汇编器MASM5.0指定的基本数据类型有BYT…

HubSpot社交媒体影响力怎么样?

HubSpot是一家在数字营销和销售领域非常知名的公司&#xff0c;以其全面的营销、销售和客户服务软件而闻名。然而&#xff0c;关于HubSpot在社交媒体上的具体影响力&#xff0c;这是一个动态的情况&#xff0c;因为社交媒体的影响力可能受到多种因素的影响&#xff0c;包括社交…

yarn 现代的包管理工具 介绍

一、前言 yarn 是一个现代的包管理工具&#xff0c;它是 npm&#xff08;Node Package Manager&#xff09;的一个替代品。yarn 由 Facebook 开发&#xff0c;并在 2016 年发布。它解决了当时 npm 的一些问题&#xff0c;尤其是在性能和安全性方面。 yarn 主要用于以下几个方面…

利用操作符解题的精彩瞬间(上)

下面是链接为了解释练习2的并且还有与操作符相关的知识。 C语言与操作符相关的经典例题-CSDN博客 操作符详解&#xff08;上&#xff09;-CSDN博客 操作符详解&#xff08;下&#xff09;-CSDN博客 目录 练习1&#xff1a;在一个整型数组中&#xff0c;只有一个数字出现一…

SpringCloud微服务常见问题

1 微服务 返回面试宝典 问题1 SpringCloud常见组件有哪些&#xff1f; SpringCloud包含的组件很多&#xff0c;有很多功能是重复的&#xff0c;其中最常见的组件包括&#xff1a; 注册中心组件&#xff1a;Eureka、Nacos等&#xff1b;负载均衡组件&#xff1a;Ribbon&…

面试题 02.07. 链表相交(力扣LeetCode)

文章目录 面试题 02.07. 链表相交题目描述解题思路c代码优化后c代码 面试题 02.07. 链表相交 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 …

【Linux】—— 信号的产生

本期&#xff0c;我们今天要将的是信号的第二个知识&#xff0c;即信号的产生。 目录 &#xff08;一&#xff09;通过终端按键产生信号 &#xff08;二&#xff09;调用系统函数向进程发信号 &#xff08;三&#xff09;由软件条件产生信号 &#xff08;四&#xff09;硬件…

【学习笔记】Vue3源码解析:第一部分-实现vue3环境搭建

课程地址&#xff1a;【已完结】全网最详细Vue3源码解析&#xff01;&#xff08;一行行带你手写Vue3源码&#xff09; 第一部分&#xff1a;实现vue3环境搭建&#xff08;对应课程的第1-3节&#xff09; VUE2与VUE3的对比&#xff1a; 也即vue2的痛点&#xff1a; 对TypeSc…

vue3前端开发框架的安全特性,非常适合现在的市场需求

vue3前端开发框架的安全特性,非常适合现在的市场需求&#xff01;现在几乎所有的前端开发&#xff0c;都是使用的vue3做了开发。下面给大家展示一下。为什么说vue3框架自带安全特性呢。 如图&#xff0c;这个是我们在浏览器内看见的&#xff0c;渲染后的数据页面信息。很齐全。…

超越人类上限的策划:百度输入法在候选词区域植入广告

一位 V2EX 用户最新发帖称&#xff0c;百度输入法的最新版本中引入了一个新功能&#xff0c;将广告直接植入到候选词区域。 具体表现为&#xff0c;当用户输入某些关键词时&#xff0c;候选词区域会显示与输入内容相关的广告链接。例如&#xff0c;用户输入“招商”时&#xf…

【C++】类与对象(二)特殊成员函数

前言 类与对象&#xff08;二&#xff09; 文章目录 一、特殊成员函数二、构造函数三、析构函数四、拷贝构造函数五、拷贝赋值运算符 一、特殊成员函数 如果在类的声明中未显式提供某个成员函数的定义&#xff0c;编译器会自动生成一个默认实现。 这包括默认构造函数、默认析构…

Flutter 开发3:创建第一个Flutter应用

Step 1: 安装Flutter 1.1 下载Flutter SDK 首先&#xff0c;你需要访问Flutter官方网站下载最新的Flutter SDK。选择适合你操作系统的安装包。 $ cd ~/development $ unzip ~/Downloads/flutter_macos_2.2.3-stable.zip1.2 更新环境变量 接下来&#xff0c;你需要将Flutter…

笔记本电脑系统Win10重装教程

当前很多用户都会使用笔记本电脑办公&#xff0c;如果笔记本电脑携带的操作系统不好用&#xff0c;就会影响到用户的办公效率&#xff0c;这时候可以给笔记本电脑重新安装一款好用的系统。以下小编带来笔记本电脑系统Win10重装教程&#xff0c;让用户们轻松给笔记本电脑重新安装…

张维迎《博弈与社会》纳什均衡与囚徒困境博弈(2)囚徒困境博弈

囚徒困境大家应该都比较熟悉了&#xff0c;我觉得这篇的意义大概在与&#xff0c;经济学术语的运用&#xff1f; 囚徒困境&#xff1a;个人理性与集体理性的矛盾 假定有两个犯罪嫌疑人共同作案。警察抓住他们以后&#xff0c;分开拘押&#xff0c;并告诉他们&#xff1a;可以选…

GWIT 和GWFI

关于燃烧的历史&#xff1a; -UL request needle flame (open fire) test to rate flammability per UL-94 Vxx UL 要求针焰&#xff08;明火&#xff09;试验以评定UL-94的易燃性。 - industry recognized that glowing wires ( caused by electrical overload) may put …

《幻兽帕鲁》游戏公司如何打造全球爆款 《幻兽帕鲁Palworld》怎么在Mac上玩?

玩法融合之外&#xff0c;《幻兽帕鲁》设计的成功和难点其实是把大部分系统及玩法结合得更紧密&#xff0c;做到多个系统之间互相强化。 “下班&#xff0c;该当帕鲁训练家了。”近日&#xff0c;记者从多个游戏群中看到&#xff0c;《幻兽帕鲁》正在取代其他游戏&#xff0c;成…

蓝桥杯-常用STL(一)

常用STL &#x1f388;1.动态数组&#x1f388;2.vector的基础使用&#x1f52d;2.1引入库&#x1f52d;2.2构造一个动态数组&#x1f52d;2.3插入元素&#x1f52d;2.4获取长度并且访问元素&#x1f52d;2.5修改元素&#x1f52d;2.6删除元素&#x1f52d;2.7清空 &#x1f38…