如何将OpenSearch日期过滤Painless脚本转换为Java代码?
将OpenSearch日期过滤Painless脚本集成到Fess Java代码
问题背景
需要把一段按日、月、年维度过滤日期的OpenSearch Painless脚本,集成到基于org.codelibs.fess:fess:14.4.0开发的Java代码中,已完成部分初始化代码,但不清楚如何正确嵌入Painless脚本内容。
解决方案
1. 处理Painless脚本的字符串转义
由于Java字符串对双引号和换行有语法要求,需将原Painless脚本转换为Java可识别的格式。推荐使用Java文本块(Java 15+)避免繁琐转义,也可对双引号手动转义。
转换后的Painless脚本Java字符串(文本块版本):
String painlessScript = """ int day; int month; int year; if ((int) doc['decisionDate.decisionDay'].size() > 0 && (int) doc['decisionDate.decisionMonth'].size() > 0 && (int) doc['decisionDate.decisionYear'].size() > 0) { day = (int) doc['decisionDate.decisionDay'].value; month = (int) doc['decisionDate.decisionMonth'].value; year = (int) doc['decisionDate.decisionYear'].value; return ChronoUnit.DAYS.between(ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of('Z')), ZonedDateTime.of(2022, 12, 13, 0, 0, 0, 0, ZoneId.of('Z'))) > 0 && ChronoUnit.DAYS.between(ZonedDateTime.of(2011, 03, 30, 0, 0, 0, 0, ZoneId.of('Z')), ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of('Z'))) > 0; } // 字段缺失时返回false,避免脚本报错 return false; """;
2. 完整的Fess Java集成代码
将脚本传入LanguageHelper.createScript,再构建查询条件并执行搜索:
final SearchEngineClient searchEngineClient = ComponentUtil.getSearchEngineClient(); final FessConfig fessConfig = ComponentUtil.getFessConfig(); final LabelTypeHelper labelTypeHelper = ComponentUtil.getLabelTypeHelper(); final LanguageHelper languageHelper = ComponentUtil.getLanguageHelper(); // 定义Painless脚本 String painlessScript = """ int day; int month; int year; if ((int) doc['decisionDate.decisionDay'].size() > 0 && (int) doc['decisionDate.decisionMonth'].size() > 0 && (int) doc['decisionDate.decisionYear'].size() > 0) { day = (int) doc['decisionDate.decisionDay'].value; month = (int) doc['decisionDate.decisionMonth'].value; year = (int) doc['decisionDate.decisionYear'].value; return ChronoUnit.DAYS.between(ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of('Z')), ZonedDateTime.of(2022, 12, 13, 0, 0, 0, 0, ZoneId.of('Z'))) > 0 && ChronoUnit.DAYS.between(ZonedDateTime.of(2011, 03, 30, 0, 0, 0, 0, ZoneId.of('Z')), ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.of('Z'))) > 0; } return false; """; // 创建Script对象 Script script = languageHelper.createScript(painlessScript); // 构建脚本查询过滤器 ScriptQueryBuilder scriptQuery = QueryBuilders.scriptQuery(script); // 构建Bool查询,添加must条件 BoolQueryBuilder boolQuery = QueryBuilders.boolQuery().must(scriptQuery); // 构建搜索请求,指定Fess索引 SearchRequest searchRequest = new SearchRequest(fessConfig.getIndexDocumentSearchIndex()); searchRequest.source(new SearchSourceBuilder().query(boolQuery)); // 执行搜索并处理结果 try { SearchResponse searchResponse = searchEngineClient.search(searchRequest); // 此处添加搜索结果的业务处理逻辑 } catch (IOException e) { // 捕获并处理搜索异常 e.printStackTrace(); }
关键说明
- 补充了字段缺失时的返回逻辑(
return false),避免脚本因字段不存在抛出异常。 - 使用
QueryBuilders构建查询条件,完全适配Fess依赖的OpenSearch客户端API规范。 SearchEngineClient是Fess封装的搜索客户端,直接调用其search方法即可执行请求。
内容的提问来源于stack exchange,提问作者Dona
相关产品推荐
相关产品推荐

