我的ES查询有一个问题,因为查询字符串中有数组索引,所以它们失败了。之所以会发生这种情况,是因为我采用了以下方法。我用下面的方法来压平我得到的JSON请求。
private void flattenJsonRequestToMap(String currentPath, JsonNode jsonNode, Map<String, Object> map) {
if (jsonNode == null || jsonNode.isNull()) {
map.remove(currentPath);
} else if (jsonNode.isObject()) {
ObjectNode objectNode = (ObjectNode) jsonNode;
Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
String pathPrefix = currentPath.isEmpty() ? "" : currentPath + ".";
while (iter.hasNext()) {
Map.Entry<String, JsonNode> entry = iter.next();
flattenJsonRequestToMap(pathPrefix + entry.getKey(), entry.getValue(), map);
}
} else if (jsonNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) jsonNode;
for (int i = 0; i < arrayNode.size(); i++) {
flattenJsonRequestToMap(currentPath + "[" + i + "]", arrayNode.get(i), map);
}
} else if (jsonNode.isValueNode()) {
ValueNode valueNode = (ValueNode) jsonNode;
map.put(currentPath, valueNode.asText());
} else {
LOGGER.error("JSONNNode unexpected field found during the flattening of JSON request" + jsonNode.asText());
}
}
当Json请求中有列表时,我的平面图如下所示。
myUserGuid -> user_testuser34_ibzwlm
numberOfOpenings -> 1
managerUserGuids[0] -> test-userYspgF1_S3P6s
accessCategories[0] -> RESTRICTED
employeeUserGuid -> user_user33_m1minh
现在,我使用上面的映射,用下面的方法构造ESQuery。
public SearchResponse searchForExactDocument(final String indexName, final Map<String, Object> queryMap)
throws IOException {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryMap.forEach((name, value) -> {
queryBuilder.must(QueryBuilders.matchPhraseQuery(name, value));
LOGGER.info("QueryMap key: {} and value: {} ", name, value);
});
return this.executeSearch(indexName, queryBuilder);
}
正如您已经看到的,它最终执行下面的查询,其中包含数组索引。我的映射结构如下。
{
name=job,
type=_doc,
mappingData={
properties={
myUserGuid ={
type=text,
fields={
keyword={
ignore_above=256,
type=keyword
}
}
},
numberOfOpenings ={
type=long
},
numOfUsage={
type=long
},
accessCategories ={
type=text,
fields={
keyword={
ignore_above=256,
type=keyword
}
}
},
managerUserGuids ={
type=text,
fields={
keyword={
ignore_above=256,
type=keyword
}
}
},
employeeUserGuid ={
type=text,
fields={
keyword={
ignore_above=256,
type=keyword
}
}
}
}
}
由于名称旁边附加了数组索引,因此查询不会返回任何搜索结果。如何处理此问题?我看到的一个选项是使用展平映射来删除数组索引,但我需要能够使用展平的映射来构造一个POJO对象,该对象具有相关字段的列表。如有任何建议,不胜感激。提前非常感谢。
ES中的列表处理方式就像一个字段只有几个值一样,因此如果您有"accessCategories": ["foo", "bar"]
,则此文档将同时匹配"accessCategories": "foo"
和"accessCategories": "bar"
,尽管无法生成仅与此数据模式匹配一个("foo"但不匹配"bar"(的查询。
如果您需要处理特定项目,您可以将列表展开为单独的字段accessCategories_0
、accessCategories_1
等。尽管Elasticsearch中一个索引中的字段总数是有限制的。