弹性Java中的查询构建



我有一个弹性查询,它在Kibana中运行得非常好,我得到了所需的结果。但是,当我试图通过使用QueryBuilders构建Query来通过Java运行它时,API不起作用,并给出以下错误。

Suppressed: org.elasticsearch.client.ResponseException: method [POST], host [http://localhost:9200], URI [/dev_skp_location/_search?typed_keys=true&max_concurrent_shard_requests=5&ignore_unavailable=false&expand_wildcards=open&allow_no_indices=true&ignore_throttled=true&search_type=dfs_query_then_fetch&batched_reduce_size=512&ccs_minimize_roundtrips=true], status line [HTTP/1.1 400 Bad Request]
{"error":{"root_cause":[{"type":"query_shard_exception","reason":"failed to create query: [nested] nested object under path [locationType] is not of nested type","index_uuid":"0nzK09YiRqmu-s9z_Um0SQ","index":"dev_skp_location"}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"dev_skp_location","node":"EIOx4chpQF2JDbGeX8Kc9Q","reason":{"type":"query_shard_exception","reason":"failed to create query: [nested] nested object under path [locationType] is not of nested type","index_uuid":"0nzK09YiRqmu-s9z_Um0SQ","index":"dev_skp_location","caused_by":{"type":"illegal_state_exception","reason":"[nested] nested object under path [locationType] is not of nested type"}}}]},"status":400}
at org.elasticsearch.client.RestClient.convertResponse(RestClient.java:326)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:296)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:270)
at org.elasticsearch.client.RestHighLevelClient.internalPerformRequest(RestHighLevelClient.java:1654)

"reason": "action [cluster:monitor/state] is unauthorized for user [skp_dev] with roles [skp_dev], this action is granted by the cluster privileges [read_ccr,transport_client,manage_ccr,monitor,manage,all]"

这是我在Kibana上工作的弹性查询,我试图获取的是具有";pur";以其名称命名,并且位置类型级别为1。

GET dev_skp_location/_search
{
"query": {
"bool":{
"must":[
{
"regexp": { "name": ".*pur*"}
},
{
"nested": {
"path": "locationType",
"query": {
"bool": {
"must": [
{ 
"match": { "locationType.level": "1" } 

}]
}
},
"score_mode": "avg"
}
}
]
}
}
}

这是我的查询生成器查询。

public Query AutoCompleteLocationQueryBuilder(String locationTerm, String level, Long tenantId){
QueryBuilder tenantQuery = QueryBuilders
.matchQuery("tenantId", tenantId);
String regexExpression = ".*" + locationTerm + "*";
QueryBuilder regexQuery = QueryBuilders.regexpQuery("name",regexExpression);
String nestedPath="locationType";
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
MatchQueryBuilder matchQuery =
QueryBuilders.matchQuery("locationType.level", level);
NestedQueryBuilder nestedQuery = QueryBuilders
.nestedQuery(nestedPath, boolQueryBuilder.must(matchQuery), ScoreMode.Avg);
QueryBuilder finalQuery = QueryBuilders.boolQuery()
.must(tenantQuery)
.must(regexQuery)
.must(nestedQuery);
return new NativeSearchQueryBuilder()
.withQuery(finalQuery)
.build()
.setPageable(PageRequest.of(0, 10));
}

你能帮我吗?我犯了什么错误?以下是Location的模型。

public class LocationSearch {
@Id
private String id = UUID.randomUUID().toString();
@MultiField(
mainField = @Field(type = FieldType.Text),
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }
)
private String locationId;
@MultiField(
mainField = @Field(type = FieldType.Text),
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }
)
private String name;
@MultiField(
mainField = @Field(type = FieldType.Text),
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }
)
private String code;
@Field(type=FieldType.Nested, name="parentLocation")
private ParentLocationSearch parentLocation;
@MultiField(
mainField = @Field(type = FieldType.Text),
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }
)
private String tenantId;
@Field(type=FieldType.Nested, name="locationType")
private LocationTypeSearch locationType;
}

LocationTypeSearch 模型

public class LocationTypeSearch {
@Id
private String id;
@MultiField(
mainField = @Field(type = FieldType.Text),
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }
)
private String name;
@Field(type=FieldType.Integer)
private String level;
}

还有索引映射功能

@Override
public void indexUserToElasticsearch(Long tenantId, User user) {
if (user == null) {
throw new ResourceNotFoundException(ErrorResponses.USER_IS_NULL);
}
UserSearch userSearch = new UserSearch();
userSearch.setUserId(user.getId().toString());
userSearch.setUserName(user.getUserName());
userSearch.setFirstName(user.getFirstName());
userSearch.setLastName(user.getLastName());
userSearch.setEmail(user.getEmail());
userSearch.setTenantId(tenantId.toString());
this.userSearchRepository.save(userSearch);
}

我刚刚使用Spring Data Elasticsearch 4.4.5对您的类LocationSearchLocationTypeSearch,只是发送一个查询以查看是否失败,而不存储任何数据并检查结果。我对此没有任何问题。

我在LocationSearch类中添加了@Document注释来定义要使用的索引,并删除了parentLocation,因为我没有用于此的类:

@Document(indexName = "location-search")
public class LocationSearch {
// ...
}

在测试中,我调用

operations.indexOps(LocationSearch.class).createWithMapping();
operations.search(autoCompleteLocationQueryBuilder("pur", "1", 42L), LocationSearch.class);

第一个调用创建索引并写入索引映射。在定义映射函数,Spring Data Elasticsearch可以通过上面的调用在新索引上创建映射。Spring Data Elasticsearch将查看属性(@Field@MultiField等(上的注释,并创建映射,在这种情况下是这样的:

{
"location-search": {
"mappings": {
"properties": {
"_class": {
"doc_values": false,
"index": false,
"type": "keyword"
},
"code": {
"fields": {
"keyword": {
"type": "keyword"
}
},
"type": "text"
},
"location-id": {
"fields": {
"keyword": {
"type": "keyword"
}
},
"type": "text"
},
"locationType": {
"properties": {
"_class": {
"doc_values": false,
"index": false,
"type": "keyword"
},
"level": {
"type": "integer"
},
"name": {
"fields": {
"keyword": {
"type": "keyword"
}
},
"type": "text"
}
},
"type": "nested"
},
"name": {
"fields": {
"keyword": {
"type": "keyword"
}
},
"type": "text"
},
"tenant-id": {
"fields": {
"keyword": {
"type": "keyword"
}
},
"type": "text"
}
}
}
}
}

您可以通过调用/<INDEX_NAME>_映射。请注意,映射定义了嵌套键入locationType字段。

Spring Data Elasticsearch创建的搜索如下:

{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{
"match": {
"tenantId": {
"query": 42,
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
},
{
"regexp": {
"name": {
"value": ".*pur*",
"flags_value": 255,
"max_determinized_states": 10000,
"boost": 1.0
}
}
},
{
"nested": {
"query": {
"bool": {
"must": [
{
"match": {
"locationType.level": {
"query": "1",
"operator": "OR",
"prefix_length": 0,
"max_expansions": 50,
"fuzzy_transpositions": true,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "locationType",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"version": true,
"explain": false
}

这基本上与您为查询显示的内容相同,它只包含在Elasticsearch客户端库添加的查询。

但是这个查询不会像您的情况那样失败。

因此,我认为索引的映射不包含正确的嵌套定义。请检查

GET /dev_skp_location/_mappings

返回,如果嵌套字段映射正确-这也是您从应用程序访问的索引?。

有关映射的更多信息,请查看Elasticsearch文档

最新更新