我们希望以多种语言搜索嵌套字段“文本”。但是,当使用不同的分析器应用其他字段时,我们永远不会得到任何命中。
我们的配置适用于非嵌套字段(例如下面示例中的“title”),因此它似乎与嵌套有关。
映射配置:
{
"properties": {
"title": {
"type": "string",
"fields": {
"en": {
"type": "string",
"analyzer": "english"
}
}
},
"texts": {
"type": "nested",
"value": {
"type": "string",
"fields": {
"en": {
"type": "string",
"analyzer": "english"
}
}
}
}
}
}
测试代码:
TransportClient testClient = new TransportClient()
.addTransportAddress(new InetSocketTransportAddress(hostname, port));
String test_index = "test_index";
IndicesExistsResponse indicesExistsResponse = testClient.admin().indices().exists(new IndicesExistsRequest(test_index))
.actionGet();
if (indicesExistsResponse.isExists()) {
testClient.admin().indices().prepareDelete(test_index).execute().actionGet();
}
testClient.admin().indices().prepareCreate(test_index).execute().actionGet();
String source = Streams.copyToStringFromClasspath("/index.json");
testClient.admin().indices()
.preparePutMapping(test_index)
.setType(ARTICLE_TYPE)
.setSource(source).execute().actionGet();
Article article = new Article();
article.title = "Winter is coming";
Text text = new Text();
text.value = "The nicest summer shoes";
text.textId = UUID.randomUUID().toString();
article.texts = Collections.singletonList(text);
testClient.index(new IndexRequest(test_index, ARTICLE_TYPE, article.articleId)
.source(objectMapper.writeValueAsBytes(article))
.refresh(true)).actionGet();
SearchHits rawTitleSearchHits = testClient.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(queryStringQuery("title:winter"))
.execute().get().getHits();
SearchHits enTitleSearchHits = testClient.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(queryStringQuery("title.en:winter"))
.execute().get().getHits();
SearchHits rawTextSearchHits = testClient.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(nestedQuery("texts", queryStringQuery("value:summer")))
.execute().get().getHits();
SearchHits enTextSearchHits = testClient.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(nestedQuery("texts", queryStringQuery("value.en:summer")))
.execute().get().getHits();
SearchHits enTextSearchMatchHits = client.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(nestedQuery("texts", matchQuery("value.en", "summer")))
.execute().get().getHits();
assertThat(rawTextSearchHits.getTotalHits(), is(1L));
assertThat(rawTitleSearchHits.getTotalHits(), is(1L));
assertThat(enTitleSearchHits.getTotalHits(), is(1L));
// Fails. Why??
assertThat(enTextSearchHits.getTotalHits(), is(1L));
// Also fails. Why??
assertThat(enTextSearchMatchHits.getTotalHits(), is(1L));
答案 0 :(得分:2)
nested
字段的映射缺少properties
结构:
{
"properties": {
"title": {
"type": "string",
"fields": {
"en": {
"type": "string",
"analyzer": "english"
}
}
},
"texts": {
"type": "nested",
"properties": { <--- this structure is missing
"value": {
"type": "string",
"fields": {
"en": {
"type": "string",
"analyzer": "english"
}
}
}
}
}
}
}
更改映射后,您需要重新编制数据索引。
<强>更新强>
最后,在您的查询中,您需要使用完整的字段路径,即texts.value.en
而不仅仅是value.en
:
SearchHits enTextSearchHits = testClient.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(nestedQuery("texts", queryStringQuery("texts.value.en:summer")))
.execute().get().getHits();
SearchHits enTextSearchMatchHits = client.prepareSearch(test_index)
.setTypes(ARTICLE_TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(nestedQuery("texts", matchQuery("texts.value.en", "summer")))
.execute().get().getHits();