弹性搜索中

时间:2015-09-01 13:12:50

标签: java elasticsearch

我们希望以多种语言搜索嵌套字段“文本”。但是,当使用不同的分析器应用其他字段时,我们永远不会得到任何命中。

我们的配置适用于非嵌套字段(例如下面示例中的“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));

1 个答案:

答案 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();