Java 中的 Elasticsearch 通配符查询 - 查找所有匹配字段并替换

Elasticsearch wildcard query in Java - find all matching fields and replace

我想更新所有以“example/one”开头的路径字段。

Map<String, Object> parameters = new HashMap<>();
parameters.put("old", "example/one");
parameters.put("new", "new/example");
    
UpdateByQueryRequest request = new UpdateByQueryRequest(index)
        .setDocTypes(type)
        .setScript(new Script(ScriptType.INLINE,
                "painless",
                "ctx._source.path = ctx._source.path.replace(params.old, params.new);",
                parameters))
        .setQuery(QueryBuilders.wildcardQuery("path.tree", "example/one*"));

client.updateByQuery(request, RequestOptions.DEFAULT);

它不工作(没有更新,没有错误 - 尝试了 prefixQuery,相同)。然而,以下查询正在更新匹配文档 (Postman)。

POST my_index/_update_by_query
{
    "script": {
        "lang": "painless",
        "inline": "ctx._source.path = ctx._source.path.replace(\"example/one\", \"new/example\")"
    },
    "query": {
        "wildcard": {
            "path.tree": {
                "value: "example/one*",
                "boost": 1.0,
                "rewrite": "constant_score"
            }
        }
    }
}

我错过了什么? Path hierarchy tokenizer 用于字段 path
非常需要您的帮助。

PS: 我无法升级到较新版本的elasticsearch。

在测试解决方案时,我首先想到它与路径字段上使用的自定义分析器有关。但它很快就被丢弃了,因为我通过 Postman 得到了预期的结果。

我最终决定采用 'two steps' 解决方案(无法通过查询 API 使用更新)。首先搜索所有匹配的文档,然后执行批量更新。

NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.wildcardQuery("path.tree", "example/one*"))
                .withSourceFilter(new FetchSourceFilter(new String[]{"_id", "path"}, null))
                .build();
        List<MyClass> result = elasticsearchRestTemplate.queryForList(query, MyClass.class);
        if(!CollectionUtils.isEmpty(result)) {
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("old", "example/one");
            parameters.put("new", "new/example");
            Script script = new Script(ScriptType.INLINE,
                    "painless",
                    "ctx._source.path = ctx._source.path.replace(params.old, params.new)",
                    parameters);
            BulkRequest request = new BulkRequest();
            for (MyClass myClass : result) {
                request.add(new UpdateRequest(index, type, myClass.getId()).script(script));
            }
            client.bulk(request, RequestOptions.DEFAULT);
        }

更新

原来是在请求中设置类型的问题。

UpdateByQueryRequest request = new UpdateByQueryRequest(index)
        .setDocTypes(type) <--------------- Remove
        .....