Невозможно найти документы в упругом поиске с заглавными буквами с помощью термина запросов. - PullRequest
1 голос
/ 29 октября 2019

Привет У меня есть приложение с загрузочной пружиной, которое подключается к упругому поиску. У меня есть несколько тестов junit, которые запускают встроенный экземпляр упругого поиска (6.6.1), создают индекс и вставляют в него некоторые документы. Некоторые из моих тестов junit не выполняются при выполнении поисковых запросов по индексу, потому что я использую термин запрос.

Я использую упругую поисковую версию 6.6.1. ниже приведено мое отображение индекса.

{
  "doc": {
    "properties": {
      "@timestamp": {
        "type": "date"
       },
      "@version": {
        "type": "text"
      },
      "account_id": {
        "type": "keyword"
      },
      "campaign_id": {
        "type": "keyword"
      },
      "delivery_ts": {
        "type": "date",
        "format": "epoch_millis"
      },
      "submission_ts": {
        "type": "date",
        "format": "epoch_millis"
      },
      "flight_id": {
        "type": "keyword"
      },
      "inventory": {
        "type": "keyword"
      },
      "msg_text": {
        "type": "keyword"
      },
      "nof_segments": {
        "type": "keyword"
      },
      "o_error": {
        "type": "keyword"
      },
      "recipient": {
        "type": "text"
      },
      "sender": {
        "type": "keyword"
      },
      "status": {
        "type": "keyword"
      },
      "campaign_name": {
        "type": "keyword"
      },
      "flight_name": {
        "type": "keyword"
      }
    }
  }
}

ниже приведены мои данные индекса, когда я даю запрос скручивания

curl -X GET "http://10.10.9.1:9200/mep*/doc/_search?pretty" -H 'Content-Type: application/json' -d'
{
    "query": {
        "match_all": {}
    }
}
'

мои данные индекса

{
  "took": 11,
  "timed_out": false,
  "_shards": {
    "total": 10,
    "successful": 10,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1016513,
    "max_score": 1,
    "hits": [
      {
        "_index": "mep-reports-2019.09.11",
        "_type": "doc",
        "_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c-353899837500",
        "_score": 1,
        "_source": {
          "account_id": "270d13e6-2f4f-4d51-99d5-92ffba5f0cb6",
          "inventory": "SMS",
          "flight_name": "test flight 001",
          "status": "ENROUTE",
          "msg_text": "Test !!!!!!!!!!!!!!1 elastic search",
          "flight_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c",
          "submission_ts": "1568197286",
          "recipient": "353899837500",
          "o_error": null,
          "nof_segments": "-1",
          "campaign_id": "0fae8662-bee9-46ac-9b3e-062f4ba55966",
          "campaign_name": "Index search petri11",
          "@version": "1",
          "sender": "800111",
          "delivery_ts": "0",
          "@timestamp": "2019-09-11T10:21:26.000Z"
        }
      },
      {
        "_index": "mep-reports-2019.09.11",
        "_type": "doc",
        "_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c-353899837503",
        "_score": 1,
        "_source": {
          "account_id": "270d13e6-2f4f-4d51-99d5-92ffba5f0cb6",
          "inventory": "SMS",
          "flight_name": "test flight 001",
          "status": "ENROUTE",
          "msg_text": "Test !!!!!!!!!!!!!!1 elastic search",
          "flight_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c",
          "submission_ts": "1568197286",
          "recipient": "353899837503",
          "o_error": null,
          "nof_segments": "-1",
          "campaign_id": "0fae8662-bee9-46ac-9b3e-062f4ba55966",
          "campaign_name": "Index search petri11",
          "@version": "1",
          "sender": "800111",
          "delivery_ts": "0",
          "@timestamp": "2019-09-11T10:21:26.000Z"
        }
      },
      {
        "_index": "mep-reports-2019.09.11",
        "_type": "doc",
        "_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c-353899837502",
        "_score": 1,
        "_source": {
          "account_id": "270d13e6-2f4f-4d51-99d5-92ffba5f0cb6",
          "inventory": "SMS",
          "flight_name": "test flight 001",
          "status": "ENROUTE",
          "msg_text": "Test !!!!!!!!!!!!!!1 elastic search",
          "flight_id": "68e8e03f-baf8-4bfc-a920-58e26edf835c",
          "submission_ts": "1568197286",
          "recipient": "353899837502",
          "o_error": null,
          "nof_segments": "-1",
          "campaign_id": "0fae8662-bee9-46ac-9b3e-062f4ba55966",
          "campaign_name": "Index search petri11",
          "@version": "1",
          "sender": "800111",
          "delivery_ts": "0",
          "@timestamp": "2019-09-11T10:21:26.000Z"
        }
      }
    ]
  }
}

ОднакоКогда я выполняю поиск в поле инвентаря или состояния, он завершается сбоем, потому что я использую запрос терминов (TermsQueryBuilder) при создании поискового запроса.

 class SearchRequestBuilder {

        private SearchRequest searchRequest;
        private SearchSourceBuilder searchSourceBuilder;
        private BoolQueryBuilder boolQueryBuilder;

        SearchRequestBuilder(String elasticSearchIndex) {
            this.searchRequest = new SearchRequest(elasticSearchIndex);
            this.searchRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
            this.searchSourceBuilder = new SearchSourceBuilder();
            this.searchRequest.source(searchSourceBuilder);
            this.boolQueryBuilder = QueryBuilders.boolQuery();
            this.searchSourceBuilder.query(this.boolQueryBuilder);
        }

        SearchRequestBuilder from(Integer pageNumber) {
            this.searchSourceBuilder.from(pageNumber);
            return this;
        }

        SearchRequestBuilder size(Integer pageSize) {
            this.searchSourceBuilder.size(pageSize);
            return this;
        }

        SearchRequestBuilder timeout(long duration, TimeUnit timeUnit) {
            this.searchSourceBuilder.timeout(new TimeValue(duration, TimeUnit.SECONDS));
            return this;
        }

        SearchRequestBuilder range(ZonedDateTime startDate, ZonedDateTime endDate) {

            RangeQueryBuilder startRangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp").gte(startDate);
            startRangeQueryBuilder.format("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

            boolQueryBuilder.must(startRangeQueryBuilder);

            RangeQueryBuilder endRangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp").lte(endDate.plusDays(1l));
            boolQueryBuilder.must(endRangeQueryBuilder);
            endRangeQueryBuilder.format("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
            return this;
        }

        SearchRequestBuilder msisdn(String msisdn) {
            if (msisdn != null) {
                if (msisdn.indexOf("*") >= 0) {
                    WildcardQueryBuilder msisdnWildCardQueryBuilder = new WildcardQueryBuilder("recipient", msisdn);
                    boolQueryBuilder.must(msisdnWildCardQueryBuilder);
                } else {
                    MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("recipient", msisdn);
                    boolQueryBuilder.must(matchQueryBuilder);
                }
            }
            return this;
        }

        SearchRequestBuilder accountId(UUID accountId) {
            if (accountId != null) {
                MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("account_id", accountId.toString());
                boolQueryBuilder.must(matchQueryBuilder);
            }
            return this;
        }

        SearchRequestBuilder campaignId(UUID campaignId) {
            if (campaignId != null) {
                MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("campaign_id", campaignId.toString());
                boolQueryBuilder.must(matchQueryBuilder);
            }
            return this;
        }

        SearchRequestBuilder flightId(UUID flightId) {
            if (flightId != null) {
                MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("flight_id", flightId.toString());
                boolQueryBuilder.must(matchQueryBuilder);
            }
            return this;
        }

        **SearchRequestBuilder cdrStatus(List<String> cdrStatus) {
            if (cdrStatus != null && cdrStatus.size() > 0) {
                TermsQueryBuilder termsQueryBuilder = new TermsQueryBuilder("status", cdrStatus);
                boolQueryBuilder.must(termsQueryBuilder);               
            }
            return this;
        }**

        **SearchRequestBuilder inventoryCode(List<String> inventoryCode) {

            if (inventoryCode != null && inventoryCode.size() > 0) {
                    TermsQueryBuilder termsQueryBuilder = new TermsQueryBuilder("inventory", inventoryCode);
                    boolQueryBuilder.must(termsQueryBuilder);   
            }**

            return this;
        }

        SearchRequestBuilder sort() {
            searchSourceBuilder.sort(new FieldSortBuilder("@timestamp").order(SortOrder.DESC));
            return this;
        }

        SearchRequestBuilder scroll(TimeValue value) {
            searchRequest.scroll(new Scroll(value));
            return this;
        }

        SearchRequestBuilder fetchSourceContext(boolean fetchSource, String[] includes, String[] excludes) {
            FetchSourceContext fetchContext = new FetchSourceContext(fetchSource, includes, excludes);
            this.searchSourceBuilder.fetchSource(fetchContext);
            return this;
        }

        SearchRequest build() {
            return this.searchRequest;
        }
    }

следующий код - фрагмент кода из junit, который запускает встроенную эластичную область. выполнить поиск и запустить тест джунита.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = PrimecastApp.class)
public class MessageHistoryReportingResourceIntTest {
embeddedElastic = EmbeddedElastic.builder().withElasticVersion("6.6.1")
                .withSetting(PopularProperties.HTTP_PORT, 57457)
                .withSetting(PopularProperties.CLUSTER_NAME, "my_cluster").withStartTimeout(5, TimeUnit.MINUTES)
                .withIndex(indexName, IndexSettings.builder().withType("doc", getJsonResourceAsStream()).build())
                .build().start();

        ObjectMapper objMapper = new ObjectMapper();
        objMapper.registerModule(new JavaTimeModule());
        objMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        objMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false);

        List<MessageHistory> messageHistories = objMapper.readValue(getMessageHistoryResourceAsStream(),
                objMapper.getTypeFactory().constructCollectionType(List.class, MessageHistory.class));
        BulkRequest request = new BulkRequest();

        Collections.sort(messageHistories, Comparator.comparing(MessageHistory::getTimeStamp));

        for (int i = 0; i < messageHistories.size(); i++) {

            request.add(new IndexRequest("mep-reports", "doc", String.valueOf(i))
                    .source(objMapper.writeValueAsString(messageHistories.get(i)), XContentType.JSON));

        }
        request.timeout(TimeValue.timeValueMinutes(5));

        client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 57457, "http")));
        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);

    @Test
    public void testSearchMessageHistoryByRangeAccountCampaignFlightRecipientInventoryAndStatus() throws Exception {
        this.restMvc
                .perform(MockMvcRequestBuilders.get("/api/message-history")
                        .param("startDate", "2019-08-31T23:00:00.000Z").param("endDate", "2019-09-11T07:06:26.287Z")
                        .param("pageNumber", "0").param("pageSize", "10")
                        .param("accountId", "a56f7e14-20f9-40e6-90c6-10604140ac5f")
                        .param("campaignId", "6f2abca3-b46d-43f3-91be-3278a8dd7dc0")
                        .param("flightId", "92348fa1-ca6c-456a-b3b2-85fba2d2deed").param("msisdn", "420736408281")
                        .param("inventoryCode", "SMS").param("cdrStatus", "ENROUTE")
                        )
                .andDo(print()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
                .andExpect(status().isOk()).andExpect(jsonPath("$.pageSize").value(10))
                .andExpect(jsonPath("$.pageNumber").value(0))
                .andExpect(jsonPath("$.totalHits").value(Matchers.greaterThan(0)))
                .andExpect(jsonPath("$.messageHistories.length()").value(Matchers.greaterThan(0)))
                .andExpect(jsonPath("$.messageHistories[0].account_id")
                        .value(Matchers.equalTo("a56f7e14-20f9-40e6-90c6-10604140ac5f")))
                .andExpect(jsonPath("$.messageHistories[0].campaign_id")
                        .value(Matchers.equalTo("6f2abca3-b46d-43f3-91be-3278a8dd7dc0")))
                .andExpect(jsonPath("$.messageHistories[0].campaign_id")
                        .value(Matchers.equalTo("6f2abca3-b46d-43f3-91be-3278a8dd7dc0")))
                .andExpect(jsonPath("$.messageHistories[0].flight_id")
                        .value(Matchers.equalTo("92348fa1-ca6c-456a-b3b2-85fba2d2deed")))
                .andExpect(jsonPath("$.messageHistories[0].recipient").value(Matchers.equalTo("420736408281")))
                .andExpect(jsonPath("$.messageHistories[0].inventory").value(Matchers.equalTo("SMS")))
                .andExpect(jsonPath("$.messageHistories[0].status").value(Matchers.equalTo("ENROUTE")));

    }

}

Вышеуказанные тесты не пройдены. Однако, если я переписываю свой тест, он будет работать так, как показано ниже

.param("inventoryCode", "sms").param("cdrStatus", "enroute")

Интернет говорит, что мне нужно изменить файл сопоставления индекса. Я попробовал пару вариантов, и это не сработало.

1 Ответ

1 голос
/ 29 октября 2019

Вы индексируете свои данные, используя KEYWORD, эти ключевые слова чувствительны к регистру. Таким образом, или вы сохраняете свои данные и запрашиваете их, используя .upper в своем приложении, ИЛИ вы переиндексируете их (в виде текста или, если вы хотите оптимизировать (и повышенную надежность), вы можете проиндексировать свое поле, чтобы оно не вызывало сомнений (https://discuss.elastic.co/t/exact-match-with-case-insensitivity/89582/8 showты как это делаешь)

"inventory": {
        "type": "keyword"
      },

      "status": {
        "type": "keyword"
      },
...