@Test
  @Ignore(
      "By default, the search request will fail if there is no mapping associated with a field. The ignore_unmapped option allows to ignore fields that have no mapping and not sort by them")
  public void shouldReturnSortedPageableResultsGivenStringQuery() {
    // todo
    // given
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    StringQuery stringQuery =
        new StringQuery(
            matchAllQuery().toString(),
            new PageRequest(0, 10),
            new Sort(new Sort.Order(Sort.Direction.ASC, "messsage")));
    // when
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class);
    // then
    assertThat(sampleEntities.getTotalElements(), is(greaterThanOrEqualTo(1L)));
  }
  @Test
  public void shouldDeleteDocumentBySpecifiedTypeUsingDeleteQuery() {
    // given
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    // when
    DeleteQuery deleteQuery = new DeleteQuery();
    deleteQuery.setQuery(fieldQuery("id", documentId));
    deleteQuery.setIndex("test-index");
    deleteQuery.setType("test-type");
    elasticsearchTemplate.delete(deleteQuery);
    // then
    SearchQuery searchQuery =
        new NativeSearchQueryBuilder().withQuery(fieldQuery("id", documentId)).build();
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
    assertThat(sampleEntities.getTotalElements(), equalTo(0L));
  }
  @Test
  public void shouldFilterSearchResultsForGivenFilter() {
    // given
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);
    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    SearchQuery searchQuery =
        new NativeSearchQueryBuilder()
            .withQuery(matchAllQuery())
            .withFilter(boolFilter().must(termFilter("id", documentId)))
            .build();
    // when
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
    // then
    assertThat(sampleEntities.getTotalElements(), equalTo(1L));
  }
  @Test
  public void shouldSortResultsGivenSortCriteria() {
    // given
    List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
    // first document
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity1 = new SampleEntity();
    sampleEntity1.setId(documentId);
    sampleEntity1.setMessage("abc");
    sampleEntity1.setRate(10);
    sampleEntity1.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery1 = new IndexQuery();
    indexQuery1.setId(documentId);
    indexQuery1.setObject(sampleEntity1);

    // second document
    String documentId2 = randomNumeric(5);
    SampleEntity sampleEntity2 = new SampleEntity();
    sampleEntity2.setId(documentId2);
    sampleEntity2.setMessage("xyz");
    sampleEntity2.setRate(5);
    sampleEntity2.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery2 = new IndexQuery();
    indexQuery2.setId(documentId2);
    indexQuery2.setObject(sampleEntity2);

    // third document
    String documentId3 = randomNumeric(5);
    SampleEntity sampleEntity3 = new SampleEntity();
    sampleEntity3.setId(documentId3);
    sampleEntity3.setMessage("xyz");
    sampleEntity3.setRate(15);
    sampleEntity3.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery3 = new IndexQuery();
    indexQuery3.setId(documentId3);
    indexQuery3.setObject(sampleEntity3);

    indexQueries.add(indexQuery1);
    indexQueries.add(indexQuery2);
    indexQueries.add(indexQuery3);

    elasticsearchTemplate.bulkIndex(indexQueries);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    SearchQuery searchQuery =
        new NativeSearchQueryBuilder()
            .withQuery(matchAllQuery())
            .withSort(new FieldSortBuilder("rate").ignoreUnmapped(true).order(SortOrder.ASC))
            .build();
    // when
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
    // then
    assertThat(sampleEntities.getTotalElements(), equalTo(3L));
    assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity2.getRate()));
  }
  @Test
  public void shouldReturnHighlightedFieldsForGivenQueryAndFields() {

    // given
    String documentId = randomNumeric(5);
    String actualMessage = "some test message";
    String highlightedMessage = "some <em>test</em> message";

    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage(actualMessage);
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    SearchQuery searchQuery =
        new NativeSearchQueryBuilder()
            .withQuery(termQuery("message", "test"))
            .withHighlightFields(new HighlightBuilder.Field("message"))
            .build();

    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(
            searchQuery,
            new ResultsMapper<SampleEntity>() {
              @Override
              public FacetedPage<SampleEntity> mapResults(SearchResponse response) {
                List<SampleEntity> chunk = new ArrayList<SampleEntity>();
                for (SearchHit searchHit : response.getHits()) {
                  if (response.getHits().getHits().length <= 0) {
                    return null;
                  }
                  SampleEntity user = new SampleEntity();
                  user.setId(searchHit.getId());
                  user.setMessage((String) searchHit.getSource().get("message"));
                  user.setHighlightedMessage(
                      searchHit.getHighlightFields().get("message").fragments()[0].toString());
                  chunk.add(user);
                }
                if (chunk.size() > 0) {
                  return new FacetedPageImpl<SampleEntity>(chunk);
                }
                return null;
              }
            });

    assertThat(sampleEntities.getContent().get(0).getHighlightedMessage(), is(highlightedMessage));
  }
  @SuppressWarnings("unchecked")
  @Test
  public void shouldGet() {
    // given
    FacetedPage page = mock(FacetedPage.class);
    given(template.queryForPage(isA(SearchQuery.class), isA(Class.class))).willReturn(page);

    // when
    commentDao.get(0, 10);

    // then
    verify(template).queryForPage(isA(SearchQuery.class), isA(Class.class));
  }
  @Test
  public void shouldSearch() {
    // given
    FacetedPage page = Mockito.mock(FacetedPage.class);
    given(elasticsearchTemplate.queryForPage(isA(SearchQuery.class), any())).willReturn(page);
    given(pageConverter.convert(page, 10)).willReturn(SearchResponse.builder().build());
    SearchRequest request = SearchRequest.builder().type("web").query("test").pageNo(0).build();

    // when
    SearchResponse actual = elasticSearchDao.search(request);

    // then
    assertThat(actual, is(notNullValue()));
    verify(elasticsearchTemplate).queryForPage(isA(SearchQuery.class), any());
    verify(pageConverter).convert(isA(FacetedPage.class), anyInt());
  }
  @Test
  public void shouldReturnSpecifiedFields() {
    // given
    String documentId = randomNumeric(5);
    String message = "some test message";
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage(message);
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);
    SearchQuery searchQuery =
        new NativeSearchQueryBuilder()
            .withQuery(matchAllQuery())
            .withIndices("test-index")
            .withTypes("test-type")
            .withFields("message")
            .build();
    // when
    Page<String> page =
        elasticsearchTemplate.queryForPage(
            searchQuery,
            new ResultsMapper<String>() {
              @Override
              public FacetedPage<String> mapResults(SearchResponse response) {
                List<String> values = new ArrayList<String>();
                for (SearchHit searchHit : response.getHits()) {
                  values.add((String) searchHit.field("message").value());
                }
                return new FacetedPageImpl<String>(values);
              }
            });
    // then
    assertThat(page, is(notNullValue()));
    assertThat(page.getTotalElements(), is(equalTo(1L)));
    assertThat(page.getContent().get(0), is(message));
  }
  @Test
  public void shouldExecuteStringQuery() {
    // given
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    StringQuery stringQuery = new StringQuery(matchAllQuery().toString());
    // when
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(stringQuery, SampleEntity.class);
    // then
    assertThat(sampleEntities.getTotalElements(), equalTo(1L));
  }
  @Test
  public void shouldDoBulkIndex() {
    // given
    List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
    // first document
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity1 = new SampleEntity();
    sampleEntity1.setId(documentId);
    sampleEntity1.setMessage("some message");
    sampleEntity1.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery1 = new IndexQuery();
    indexQuery1.setId(documentId);
    indexQuery1.setObject(sampleEntity1);
    indexQueries.add(indexQuery1);

    // second document
    String documentId2 = randomNumeric(5);
    SampleEntity sampleEntity2 = new SampleEntity();
    sampleEntity2.setId(documentId2);
    sampleEntity2.setMessage("some message");
    sampleEntity2.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery2 = new IndexQuery();
    indexQuery2.setId(documentId2);
    indexQuery2.setObject(sampleEntity2);

    indexQueries.add(indexQuery2);
    // when
    elasticsearchTemplate.bulkIndex(indexQueries);
    elasticsearchTemplate.refresh(SampleEntity.class, true);
    // then
    SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
    assertThat(sampleEntities.getTotalElements(), is(equalTo(2L)));
  }
  @Test
  public void shouldReturnPageForGivenSearchQuery() {
    // given
    String documentId = randomNumeric(5);
    SampleEntity sampleEntity = new SampleEntity();
    sampleEntity.setId(documentId);
    sampleEntity.setMessage("some message");
    sampleEntity.setVersion(System.currentTimeMillis());

    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(documentId);
    indexQuery.setObject(sampleEntity);

    elasticsearchTemplate.index(indexQuery);
    elasticsearchTemplate.refresh(SampleEntity.class, true);

    SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).build();
    // when
    Page<SampleEntity> sampleEntities =
        elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
    // then
    assertThat(sampleEntities, is(notNullValue()));
    assertThat(sampleEntities.getTotalElements(), greaterThanOrEqualTo(1L));
  }