@Test
  public void testMultiMatchQuery() throws Exception {
    try {
      client.admin().indices().prepareDelete("test").execute().actionGet();
    } catch (Exception e) {
      // ignore
    }

    client
        .admin()
        .indices()
        .prepareCreate("test")
        .setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1))
        .execute()
        .actionGet();

    client
        .prepareIndex("test", "type1", "1")
        .setSource("field1", "value1", "field2", "value4", "field3", "value3")
        .execute()
        .actionGet();
    client
        .prepareIndex("test", "type1", "2")
        .setSource("field1", "value2", "field2", "value5", "field3", "value2")
        .execute()
        .actionGet();
    client
        .prepareIndex("test", "type1", "3")
        .setSource("field1", "value3", "field2", "value6", "field3", "value1")
        .execute()
        .actionGet();
    client.admin().indices().prepareRefresh("test").execute().actionGet();

    MultiMatchQueryBuilder builder =
        QueryBuilders.multiMatchQuery("value1 value2 value4", "field1", "field2");
    SearchResponse searchResponse =
        client
            .prepareSearch()
            .setQuery(builder)
            .addFacet(FacetBuilders.termsFacet("field1").field("field1"))
            .execute()
            .actionGet();

    assertThat(searchResponse.hits().totalHits(), equalTo(2l));
    assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));
    assertThat("2", equalTo(searchResponse.hits().getAt(1).id()));

    builder.useDisMax(false);
    searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();

    assertThat(searchResponse.hits().totalHits(), equalTo(2l));
    assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));
    assertThat("2", equalTo(searchResponse.hits().getAt(1).id()));

    client.admin().indices().prepareRefresh("test").execute().actionGet();
    builder =
        QueryBuilders.multiMatchQuery("value1", "field1", "field2")
            .operator(
                MatchQueryBuilder.Operator
                    .AND); // Operator only applies on terms inside a field! Fields are always OR-ed
                           // together.
    searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(1l));
    assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));

    client.admin().indices().prepareRefresh("test").execute().actionGet();
    builder =
        QueryBuilders.multiMatchQuery("value1", "field1", "field3^1.5")
            .operator(
                MatchQueryBuilder.Operator
                    .AND); // Operator only applies on terms inside a field! Fields are always OR-ed
                           // together.
    searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(2l));
    assertThat("3", equalTo(searchResponse.hits().getAt(0).id()));
    assertThat("1", equalTo(searchResponse.hits().getAt(1).id()));

    client.admin().indices().prepareRefresh("test").execute().actionGet();
    builder =
        QueryBuilders.multiMatchQuery("value1")
            .field("field1")
            .field("field3", 1.5f)
            .operator(
                MatchQueryBuilder.Operator
                    .AND); // Operator only applies on terms inside a field! Fields are always OR-ed
                           // together.
    searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(2l));
    assertThat("3", equalTo(searchResponse.hits().getAt(0).id()));
    assertThat("1", equalTo(searchResponse.hits().getAt(1).id()));

    // Test lenient
    client
        .prepareIndex("test", "type1", "3")
        .setSource("field1", "value7", "field2", "value8", "field4", 5)
        .execute()
        .actionGet();
    client.admin().indices().prepareRefresh("test").execute().actionGet();

    builder = QueryBuilders.multiMatchQuery("value1", "field1", "field2", "field4");
    try {
      client.prepareSearch().setQuery(builder).execute().actionGet();
      fail("Exception expected");
    } catch (SearchPhaseExecutionException e) {
      assertThat(e.shardFailures()[0].status(), equalTo(RestStatus.BAD_REQUEST));
    }

    builder.lenient(true);
    searchResponse = client.prepareSearch().setQuery(builder).execute().actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(1l));
    assertThat("1", equalTo(searchResponse.hits().getAt(0).id()));
  }
  @Test
  public void testIndexOptions() throws Exception {
    try {
      client.admin().indices().prepareDelete("test").execute().actionGet();
    } catch (Exception e) {
      // ignore
    }

    client
        .admin()
        .indices()
        .prepareCreate("test")
        .addMapping(
            "type1",
            jsonBuilder()
                .startObject()
                .startObject("type1")
                .startObject("properties")
                .startObject("field1")
                .field("index_options", "docs")
                .field("type", "string")
                .endObject()
                .endObject()
                .endObject()
                .endObject())
        .setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1))
        .execute()
        .actionGet();

    client
        .prepareIndex("test", "type1", "1")
        .setSource("field1", "quick brown fox", "field2", "quick brown fox")
        .execute()
        .actionGet();
    client
        .prepareIndex("test", "type1", "2")
        .setSource("field1", "quick lazy huge brown fox", "field2", "quick lazy huge brown fox")
        .setRefresh(true)
        .execute()
        .actionGet();

    SearchResponse searchResponse =
        client
            .prepareSearch()
            .setQuery(
                QueryBuilders.matchQuery("field2", "quick brown")
                    .type(MatchQueryBuilder.Type.PHRASE)
                    .slop(0))
            .execute()
            .actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(1l));
    try {
      client
          .prepareSearch()
          .setQuery(
              QueryBuilders.matchQuery("field1", "quick brown")
                  .type(MatchQueryBuilder.Type.PHRASE)
                  .slop(0))
          .execute()
          .actionGet();
    } catch (SearchPhaseExecutionException e) {
      assertTrue(
          e.getMessage()
              .endsWith(
                  "IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery (term=quick)]; }"));
    }
  }
  @Test
  public void testCommonTermsQuery() throws Exception {
    try {
      client.admin().indices().prepareDelete("test").execute().actionGet();
    } catch (Exception e) {
      // ignore
    }

    client
        .admin()
        .indices()
        .prepareCreate("test")
        .addMapping(
            "type1",
            jsonBuilder()
                .startObject()
                .startObject("type1")
                .startObject("properties")
                .startObject("field1")
                .field("analyzer", "whitespace")
                .field("type", "string")
                .endObject()
                .endObject()
                .endObject()
                .endObject())
        .setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1))
        .execute()
        .actionGet();

    client
        .prepareIndex("test", "type1", "1")
        .setSource("field1", "the quick brown fox")
        .execute()
        .actionGet();
    client
        .prepareIndex("test", "type1", "2")
        .setSource("field1", "the quick lazy huge brown fox jumps over the tree")
        .execute()
        .actionGet();
    client
        .prepareIndex("test", "type1", "3")
        .setSource("field1", "quick lazy huge brown")
        .setRefresh(true)
        .execute()
        .actionGet();

    SearchResponse searchResponse =
        client
            .prepareSearch()
            .setQuery(QueryBuilders.commonTerms("field1", "the quick brown").cutoffFrequency(3))
            .execute()
            .actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(2l));
    assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1"));
    assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("2"));

    searchResponse =
        client
            .prepareSearch()
            .setQuery(
                QueryBuilders.commonTerms("field1", "the quick brown")
                    .cutoffFrequency(3)
                    .lowFreqOperator(Operator.OR))
            .execute()
            .actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(3l));
    assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1"));
    assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("2"));
    assertThat(searchResponse.getHits().getHits()[2].getId(), equalTo("3"));

    searchResponse =
        client
            .prepareSearch()
            .setQuery(
                QueryBuilders.commonTerms("field1", "the quick brown")
                    .cutoffFrequency(3)
                    .analyzer("standard"))
            .execute()
            .actionGet();
    assertThat(searchResponse.hits().totalHits(), equalTo(3l));
    // standard drops "the" since its a stopword
    assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1"));
    assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("3"));
    assertThat(searchResponse.getHits().getHits()[2].getId(), equalTo("2"));
  }