我想将json字符串序列化为Elasticsearch SearchResponse对象。如果json字符串不包含聚合,则可以正常工作。
如果json字符串包含聚合,XContentParser会抛出一个ParsingException[无法解析键控为[target\u字段]异常的聚合。
我用于将json字符串序列化为Elasticsearch SearchResponse对象的代码:
Settings settings = Settings.builder().build();
SearchModule searchModule = new SearchModule(settings, false, new ArrayList<>());
NamedXContentRegistry xContentRegistry = new NamedXContentRegistry(searchModule.getNamedXContents());
JsonXContentParser xContentParser = new JsonXContentParser(xContentRegistry,
new JsonFactory().createParser(json));
SearchResponse response = SearchResponse.fromXContent(xContentParser);
似乎我必须将聚合注册到NamedXContentRegistry,但我不知道如何注册。
您需要添加?键入请求URL的\u键,例如启动搜索?键入\u键,请查看此参考。
并且您最好像框架源代码一样在
NamedXContent注册表
中添加更多parse
注册表。以下是所有注册表条目:
private List<NamedXContentRegistry.Entry> getProvidedNamedXContents() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
for (NamedXContentProvider service : ServiceLoader.load(NamedXContentProvider.class)) {
entries.addAll(service.getNamedXContentParsers());
}
return entries;
}
private NamedXContentRegistry getDefaultNamedXContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
entries.addAll(getDefaultNamedXContents());
entries.addAll(getProvidedNamedXContents());
return new NamedXContentRegistry(entries);
}
private List<NamedXContentRegistry.Entry> getDefaultNamedXContents() {
Map<String, ContextParser<Object, ? extends Aggregation>> map = new HashMap<>();
map.put("cardinality", (p, c) -> ParsedCardinality.fromXContent(p, (String) c));
map.put("hdr_percentiles", (p, c) -> ParsedHDRPercentiles.fromXContent(p, (String) c));
map.put("hdr_percentile_ranks", (p, c) -> ParsedHDRPercentileRanks.fromXContent(p, (String) c));
map.put("tdigest_percentiles", (p, c) -> ParsedTDigestPercentiles.fromXContent(p, (String) c));
map.put("tdigest_percentile_ranks", (p, c) -> ParsedTDigestPercentileRanks.fromXContent(p, (String) c));
map.put("percentiles_bucket", (p, c) -> ParsedPercentilesBucket.fromXContent(p, (String) c));
map.put("min", (p, c) -> ParsedMin.fromXContent(p, (String) c));
map.put("max", (p, c) -> ParsedMax.fromXContent(p, (String) c));
map.put("sum", (p, c) -> ParsedSum.fromXContent(p, (String) c));
map.put("avg", (p, c) -> ParsedAvg.fromXContent(p, (String) c));
map.put("value_count", (p, c) -> ParsedValueCount.fromXContent(p, (String) c));
map.put("simple_value", (p, c) -> ParsedSimpleValue.fromXContent(p, (String) c));
map.put("derivative", (p, c) -> ParsedDerivative.fromXContent(p, (String) c));
map.put("bucket_metric_value", (p, c) -> ParsedBucketMetricValue.fromXContent(p, (String) c));
map.put("stats", (p, c) -> ParsedStats.fromXContent(p, (String) c));
map.put("stats_bucket", (p, c) -> ParsedStatsBucket.fromXContent(p, (String) c));
map.put("extended_stats", (p, c) -> ParsedExtendedStats.fromXContent(p, (String) c));
map.put("extended_stats_bucket", (p, c) -> ParsedExtendedStatsBucket.fromXContent(p, (String) c));
map.put("geo_bounds", (p, c) -> ParsedGeoBounds.fromXContent(p, (String) c));
map.put("geo_centroid", (p, c) -> ParsedGeoCentroid.fromXContent(p, (String) c));
map.put("histogram", (p, c) -> ParsedHistogram.fromXContent(p, (String) c));
map.put("date_histogram", (p, c) -> ParsedDateHistogram.fromXContent(p, (String) c));
map.put("sterms", (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
map.put("lterms", (p, c) -> ParsedLongTerms.fromXContent(p, (String) c));
map.put("dterms", (p, c) -> ParsedDoubleTerms.fromXContent(p, (String) c));
map.put("missing", (p, c) -> ParsedMissing.fromXContent(p, (String) c));
map.put("nested", (p, c) -> ParsedNested.fromXContent(p, (String) c));
map.put("reverse_nested", (p, c) -> ParsedReverseNested.fromXContent(p, (String) c));
map.put("global", (p, c) -> ParsedGlobal.fromXContent(p, (String) c));
map.put("filter", (p, c) -> ParsedFilter.fromXContent(p, (String) c));
map.put("sampler", (p, c) -> ParsedSampler.fromXContent(p, (String) c));
map.put("geohash_grid", (p, c) -> ParsedGeoHashGrid.fromXContent(p, (String) c));
map.put("range", (p, c) -> ParsedRange.fromXContent(p, (String) c));
map.put("date_range", (p, c) -> ParsedDateRange.fromXContent(p, (String) c));
map.put("geo_distance", (p, c) -> ParsedGeoDistance.fromXContent(p, (String) c));
map.put("filters", (p, c) -> ParsedFilters.fromXContent(p, (String) c));
map.put("adjacency_matrix", (p, c) -> ParsedAdjacencyMatrix.fromXContent(p, (String) c));
map.put("siglterms", (p, c) -> ParsedSignificantLongTerms.fromXContent(p, (String) c));
map.put("sigsterms", (p, c) -> ParsedSignificantStringTerms.fromXContent(p, (String) c));
map.put("scripted_metric", (p, c) -> ParsedScriptedMetric.fromXContent(p, (String) c));
map.put("ip_range", (p, c) -> ParsedBinaryRange.fromXContent(p, (String) c));
map.put("top_hits", (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
map.put("composite", (p, c) -> ParsedComposite.fromXContent(p, (String) c));
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream()
.map((entry) -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField((String) entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
entries.add(new NamedXContentRegistry.Entry(Suggest.Suggestion.class, new ParseField("term"), (parser, context) -> TermSuggestion.fromXContent(parser, (String) context)));
entries.add(new NamedXContentRegistry.Entry(Suggest.Suggestion.class, new ParseField("phrase"), (parser, context) -> PhraseSuggestion.fromXContent(parser, (String) context)));
entries.add(new NamedXContentRegistry.Entry(Suggest.Suggestion.class, new ParseField("completion"), (parser, context) -> CompletionSuggestion.fromXContent(parser, (String) context)));
return entries;
}
根据上面的答案,我设法这样做了:
我写了一个这样的JSON:
XContentBuilder builder = XContentFactory.jsonBuilder();
response.toXContent(builder, ToXContent.EMPTY_PARAMS);
String result = Strings.toString(builder);
然后我设法这样读:
try {
NamedXContentRegistry registry = new NamedXContentRegistry(getDefaultNamedXContents());
XContentParser parser = JsonXContent.jsonXContent.createParser(registry, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, result);
SearchResponse searchResponse = SearchResponse.fromXContent(parser);
} catch (IOException e) {
System.out.println("exception " + e);
} catch (Exception e) {
System.out.println("exception " + e);
}
public static List<NamedXContentRegistry.Entry> getDefaultNamedXContents() {
Map<String, ContextParser<Object, ? extends Aggregation>> map = new HashMap<>();
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream()
.map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
return entries;
}
希望它能起作用:)
背景:
我写这个答案是因为我有创建SearchSecurity对象的经验,目的是编写一个Java单元测试。目标是从Elasticsearch查询中获取任何JSON响应对象,将其编入SearchSecurity对象,并单元测试创建可消耗输出的业务逻辑。
我们正在使用高级rest客户端Elasticsearch 6.7,并使用Elastic的POJO解析SearchResponse(而不是仅仅执行一个.toString()并使用GSON或Jackson进行操作)。
解决方案说明:
Elasticsearch的高级rest客户端一般解析来自低级rest客户端的结果。SearchRequest的响应JSON在search方法第129行的RestHighLevelClient中转换为SearchACK Object。此方法在第1401行调用performRequest estAndParseEntity,它接受entityParser
作为CheckedFunction
关于解决方案:
在阅读了Elasticsearch对此的讨论之后,如果您想将Elastic的JSON响应注入SearchResponse对象,那么有必要创建NamedXContentRegistry和Xcontent测试列表,您必须重新创建解析。这是一种辅助方法,来源于Elastic的讨论:
public static List<NamedXContentRegistry.Entry> getDefaultNamedXContents() {
Map<String, ContextParser<Object, ? extends Aggregation>> map = new HashMap<>();
map.put(TopHitsAggregationBuilder.NAME, (p, c) -> ParsedTopHits.fromXContent(p, (String) c));
map.put(StringTerms.NAME, (p, c) -> ParsedStringTerms.fromXContent(p, (String) c));
List<NamedXContentRegistry.Entry> entries = map.entrySet().stream()
.map(entry -> new NamedXContentRegistry.Entry(Aggregation.class, new ParseField(entry.getKey()), entry.getValue()))
.collect(Collectors.toList());
return entries;
}
上面代码中的map需要包含测试所需的所有聚合。有两个以上,为简洁起见,这里有两个。
使用这个助手getNamedXContents()方法,现在可以使用以下方法获取JSON字符串并将其注入SearchResponse。同样来源于Elastic的讨论:
public static SearchResponse getSearchResponseFromJson(String jsonResponse){
try {
NamedXContentRegistry registry = new NamedXContentRegistry(getDefaultNamedXContents());
XContentParser parser = JsonXContent.jsonXContent.createParser(registry, jsonResponse);
return SearchResponse.fromXContent(parser);
} catch (IOException e) {
System.out.println("exception " + e);
}catch (Exception e){
System.out.println("exception " + e);
}
return new SearchResponse();
}
使用聚合结果应用解决方案:
Elasticsearch需要提示,以了解要将其解析为哪种类型的聚合。添加时由elastic提供提示?键入查询的\u键。有关聚合类型提示的Elasticsearch文档中显示了一个示例。
要将JSON字符串注入SearchResponse对象,必须(1)使用上面的方法,(2)注入一个包含类型提示的字符串。
主要来源:
https://discuss.elastic.co/t/elasticsearch-json-response-to-searchresponse-object/124394/6
注:大约2015年有很多文章说这是不可能的。这显然是错误的。
我正在构建一个计算器,为了让计算器工作,我需要将字符串中的所有整数转换为双数。例如,如果我有一个字符串:3*8 5/2-4,我想将其转换为:3.0*8.0 5.0/2.0-4.0。我该怎么做? 编辑:如果我有这个字符串:3.0*8.0 5.0/2.0-4,我想将他转换为:3.0*8.0 5.0/2.0-4.0
问题内容: 我想获取一串字符串并将其转换为单词对流。例如: 我有: 我想要:。 这几乎与Zipping相同,如使用带有Lambda的JDK8的Zipping流中概述的那样(java.util.stream.Streams.zip) 但是,这会产生: 以下代码有效,但显然是错误的方法(不是线程安全的等): 问题答案: 如果你: 不喜欢使用流中所有字符串创建列表的想法 不想使用外部库 喜欢弄脏你的手
我有一个带有转义Unicode字符的字符串,我想将它转换为常规Unicode字母。例如: 应成为 我知道,当我打印第一个字符串时,它已经显示。我的问题是我从一个文件中读取文件名,然后我搜索它们。文件中的文件名是用Unicode编码转义的,当我搜索这些文件时,我找不到它们,因为它搜索的文件名中有。
问题内容: 指定直方图聚合时,是否可以将字符串转换为浮点数?因为我的文档中的字段是浮点型的,但没有通过Elasticsearch解析,因此当我尝试使用字符串字段求和时,它将引发下一个错误。 我知道我可以更改映射,但是对于我有的用例,如果在编写字段的聚合时可以指定类似“ script:_value.tofloat()”的内容,则将更加方便。 这是我的代码: } 问题答案: 你需要这个 对于称为的字段
我想从属性转换空字符串值,并在API响应模型对象中用替换它。 我尝试了这个解决方案,但它在类级别上不起作用。
问题内容: 我正在阅读有关python的新f字符串的 博客 ,它们看起来很整洁。但是,我希望能够从字符串或文件中加载f字符串。 我似乎找不到任何执行此操作的字符串方法或其他函数。 从上面我的链接中的示例: 但是,如果我有琴弦怎么办?我希望能够像这样: 事实证明,我已经可以执行类似的操作并获得性能提高。即: 问题答案: f字符串是代码。不仅以安全的方式(当然,字符串文字就是代码),而且以危险的任意代