package com.github.obourgain.elasticsearch.http.handler.document; import static org.elasticsearch.client.Requests.indexAliasesRequest; import static org.elasticsearch.client.Requests.indexRequest; import static org.elasticsearch.client.Requests.moreLikeThisRequest; import static org.elasticsearch.client.Requests.refreshRequest; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.FilterBuilders.termFilter; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.assertj.core.api.Assertions; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.mlt.MoreLikeThisRequest; import org.elasticsearch.client.Requests; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.index.query.MoreLikeThisQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.lookup.SourceLookup; import org.junit.Test; import com.github.obourgain.elasticsearch.http.AbstractTest; import com.github.obourgain.elasticsearch.http.response.entity.Hit; import com.github.obourgain.elasticsearch.http.handler.search.search.SearchResponse; @SuppressWarnings("LongLiteralLowerCaseSuffix") public class MoreLikeThisActionHandlerTest extends AbstractTest { // remember maintain these tests, taken from org.elasticsearch.mlt.MoreLikeThisActionTests @Test public void testSimpleMoreLikeThis() throws Exception { logger.info("Creating index test"); assertAcked(prepareCreate("test").addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("text").field("type", "string").endObject() .endObject().endObject().endObject())); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); client().index(indexRequest("test").type("type1").id("1").source(jsonBuilder().startObject().field("text", "lucene").endObject())).actionGet(); client().index(indexRequest("test").type("type1").id("2").source(jsonBuilder().startObject().field("text", "lucene release").endObject())).actionGet(); client().admin().indices().refresh(refreshRequest()).actionGet(); logger.info("Running moreLikeThis"); SearchResponse mltResponse = httpClient.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).get(); assertHitCount(mltResponse, 1l); } @Test public void testSimpleMoreLikeOnLongField() throws Exception { logger.info("Creating index test"); assertAcked(prepareCreate("test").addMapping("type1", "some_long", "type=long")); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); client().index(indexRequest("test").type("type1").id("1").source(jsonBuilder().startObject().field("some_long", 1367484649580l).endObject())).actionGet(); client().index(indexRequest("test").type("type2").id("2").source(jsonBuilder().startObject().field("some_long", 0).endObject())).actionGet(); client().index(indexRequest("test").type("type1").id("3").source(jsonBuilder().startObject().field("some_long", -666).endObject())).actionGet(); client().admin().indices().refresh(refreshRequest()).actionGet(); logger.info("Running moreLikeThis"); SearchResponse mltResponse = httpClient.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).get(); assertHitCount(mltResponse, 0l); } @Test public void testMoreLikeThisWithAliases() throws Exception { logger.info("Creating index test"); assertAcked(prepareCreate("test").addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("text").field("type", "string").endObject() .endObject().endObject().endObject())); logger.info("Creating aliases alias release"); client().admin().indices().aliases(indexAliasesRequest().addAlias("release", termFilter("text", "release"), "test")).actionGet(); client().admin().indices().aliases(indexAliasesRequest().addAlias("beta", termFilter("text", "beta"), "test")).actionGet(); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); client().index(indexRequest("test").type("type1").id("1").source(jsonBuilder().startObject().field("text", "lucene beta").endObject())).actionGet(); client().index(indexRequest("test").type("type1").id("2").source(jsonBuilder().startObject().field("text", "lucene release").endObject())).actionGet(); client().index(indexRequest("test").type("type1").id("3").source(jsonBuilder().startObject().field("text", "elasticsearch beta").endObject())).actionGet(); client().index(indexRequest("test").type("type1").id("4").source(jsonBuilder().startObject().field("text", "elasticsearch release").endObject())).actionGet(); client().admin().indices().refresh(refreshRequest()).actionGet(); logger.info("Running moreLikeThis on index"); SearchResponse mltResponse = httpClient.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).get(); assertHitCount(mltResponse, 2l); logger.info("Running moreLikeThis on beta shard"); mltResponse = httpClient.moreLikeThis(moreLikeThisRequest("beta").type("type1").id("1").minTermFreq(1).minDocFreq(1)).get(); assertHitCount(mltResponse, 1l); assertThat(mltResponse.getHits().getAt(0).getId(), equalTo("3")); logger.info("Running moreLikeThis on release shard"); mltResponse = httpClient.moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1).searchIndices("release")).get(); assertHitCount(mltResponse, 1l); assertThat(mltResponse.getHits().getAt(0).getId(), equalTo("2")); // remove node client from copied test } // no need to copy // testMoreLikeThisIssue2197 // testMoreLikeWithCustomRouting // testMoreLikeThisIssueRoutingNotSerialized // testNumericField @Test public void testSimpleMoreLikeInclude() throws Exception { logger.info("Creating index test"); assertAcked(prepareCreate("test").addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("text").field("type", "string").endObject() .endObject().endObject().endObject())); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); client().index(indexRequest("test").type("type1").id("1").source( jsonBuilder().startObject() .field("text", "Apache Lucene is a free/open source information retrieval software library").endObject())) .actionGet(); client().index(indexRequest("test").type("type1").id("2").source( jsonBuilder().startObject() .field("text", "Lucene has been ported to other programming languages").endObject())) .actionGet(); client().admin().indices().refresh(refreshRequest()).actionGet(); logger.info("Running More Like This with include true"); SearchResponse mltResponse = httpClient.moreLikeThis( moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1).include(true).percentTermsToMatch(0)) .get(); assertOrderedSearchHits(mltResponse, "1", "2"); mltResponse = httpClient.moreLikeThis( moreLikeThisRequest("test").type("type1").id("2").minTermFreq(1).minDocFreq(1).include(true).percentTermsToMatch(0)) .get(); assertOrderedSearchHits(mltResponse, "2", "1"); logger.info("Running More Like This with include false"); mltResponse = httpClient.moreLikeThis( moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1).percentTermsToMatch(0)) .get(); assertSearchHits(mltResponse, "2"); } @Test public void testMoreLikeThisBodyFromSize() throws Exception { String index = "test"; logger.info("Creating index test"); assertAcked(prepareCreate(index).addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("text").field("type", "string").endObject() .endObject().endObject().endObject())); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); List<IndexRequestBuilder> builders = new ArrayList<>(10); for (int i = 1; i <= 10; i++) { builders.add(client().prepareIndex(index, "type1").setSource("text", "lucene").setId(String.valueOf(i))); } indexRandom(true, builders); logger.info("'size' set but 'search_from' and 'search_size' kept to defaults"); SearchResponse mltResponse = httpClient.moreLikeThis( moreLikeThisRequest(index).type("type1").id("1").minTermFreq(1).minDocFreq(1).include(true) .searchSource(SearchSourceBuilder.searchSource().size(5))) .get(); assertShardsSuccessfulForIT(mltResponse.getShards(), "test"); assertEquals(mltResponse.getHits().getHits().size(), 5); logger.info("'from' set but 'search_from' and 'search_size' kept to defaults"); mltResponse = httpClient.moreLikeThis( moreLikeThisRequest(index).type("type1").id("1").minTermFreq(1).minDocFreq(1).include(true) .searchSource(SearchSourceBuilder.searchSource().from(5))) .get(); assertShardsSuccessfulForIT(mltResponse.getShards(), "test"); assertEquals(mltResponse.getHits().getHits().size(), 5); logger.info("When set, 'search_from' and 'search_size' should override 'from' and 'size'"); mltResponse = httpClient.moreLikeThis( moreLikeThisRequest(index).type("type1").id("1").minTermFreq(1).minDocFreq(1).include(true) .searchSize(10).searchFrom(2) .searchSource(SearchSourceBuilder.searchSource().size(1).from(1))) .get(); assertShardsSuccessfulForIT(mltResponse.getShards(), index); assertEquals(mltResponse.getHits().getHits().size(), 8); } @Test public void testSimpleMoreLikeThisIds() throws Exception { logger.info("Creating index test"); assertAcked(prepareCreate("test").addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties") .startObject("text").field("type", "string").endObject() .endObject().endObject().endObject())); logger.info("Running Cluster Health"); assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); logger.info("Indexing..."); List<IndexRequestBuilder> builders = new ArrayList<>(); builders.add(client().prepareIndex("test", "type1").setSource("text", "lucene").setId("1")); builders.add(client().prepareIndex("test", "type1").setSource("text", "lucene release").setId("2")); builders.add(client().prepareIndex("test", "type1").setSource("text", "apache lucene").setId("3")); indexRandom(true, builders); logger.info("Running MoreLikeThis"); MoreLikeThisQueryBuilder queryBuilder = QueryBuilders.moreLikeThisQuery("text").ids("1").include(true).minTermFreq(1).minDocFreq(1); SearchResponse mltResponse = httpClient.search(Requests.searchRequest("test").types("type1").source(new SearchSourceBuilder().query(queryBuilder))).get(); assertHitCount(mltResponse, 3l); } private static void assertHitCount(SearchResponse mltResponse, long expectedHitCount) { Assertions.assertThat(mltResponse.getHits().getTotal()).isEqualTo(expectedHitCount); } public static void assertSearchHits(SearchResponse searchResponse, String... ids) { Assertions.assertThat(searchResponse.getHits().getHits().size()).isEqualTo(ids.length); Set<String> idsSet = new HashSet<>(Arrays.asList(ids)); Assertions.assertThat(searchResponse.getHits().getHits()).extracting("id").containsExactly(idsSet.toArray()); } public static void assertOrderedSearchHits(SearchResponse searchResponse, String... ids) { Assertions.assertThat(searchResponse.getHits().getHits().size()).isEqualTo(ids.length); for (int i = 0; i < ids.length; i++) { Hit hit = searchResponse.getHits().getHits().get(i); Assertions.assertThat(hit.getId()).isEqualTo(ids[i]); } } }