Browse Source

More Like This Query: allow for both 'like_text' and 'docs/ids' to be specified.

Closes #6246
Alex Ksikes 11 years ago
parent
commit
2546c06131

+ 1 - 1
docs/reference/query-dsl/queries/mlt-query.asciidoc

@@ -74,7 +74,7 @@ The `more_like_this` top level parameters include:
 |`fields` |A list of the fields to run the more like this query against.
 Defaults to the `_all` field.
 
-|`like_text` |The text to find documents like it, *required* if `ids` is
+|`like_text` |The text to find documents like it, *required* if `ids` or `docs` are
 not specified.
 
 |`ids` or `docs` |A list of documents following the same syntax as the 

+ 6 - 2
src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryParser.java

@@ -158,8 +158,8 @@ public class MoreLikeThisQueryParser implements QueryParser {
             }
         }
 
-        if ((mltQuery.getLikeText() == null && items.isEmpty()) || (mltQuery.getLikeText() != null && !items.isEmpty())) {
-            throw new QueryParsingException(parseContext.index(), "more_like_this requires either 'like_text' or 'ids/docs' to be specified");
+        if (mltQuery.getLikeText() == null && items.isEmpty()) {
+            throw new QueryParsingException(parseContext.index(), "more_like_this requires at least 'like_text' or 'ids/docs' to be specified");
         }
 
         if (analyzer == null) {
@@ -217,6 +217,10 @@ public class MoreLikeThisQueryParser implements QueryParser {
                 ConstantScoreQuery query = new ConstantScoreQuery(filter);
                 boolQuery.add(query, BooleanClause.Occur.MUST_NOT);
             }
+            // add the possible mlt query with like_text
+            if (mltQuery.getLikeText() != null) {
+                boolQuery.add(mltQuery, BooleanClause.Occur.SHOULD);
+            }
             return boolQuery;
         }
 

+ 14 - 5
src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java

@@ -1696,16 +1696,25 @@ public class SimpleIndexQueryParserTests extends ElasticsearchTestCase {
         Query parsedQuery = queryParser.parse(query).query();
         assertThat(parsedQuery, instanceOf(BooleanQuery.class));
         BooleanQuery booleanQuery = (BooleanQuery) parsedQuery;
-        assertThat(booleanQuery.getClauses().length, is(likeTexts.size()));
+        assertThat(booleanQuery.getClauses().length, is(likeTexts.size() + 1));
 
+        // check each clause is for each item
+        BooleanClause[] boolClauses = booleanQuery.getClauses();
         for (int i=0; i<likeTexts.size(); i++) {
-            BooleanClause booleanClause = booleanQuery.getClauses()[i];
-            assertThat(booleanClause.getOccur(), is(BooleanClause.Occur.SHOULD));
-            assertThat(booleanClause.getQuery(), instanceOf(MoreLikeThisQuery.class));
-            MoreLikeThisQuery mltQuery = (MoreLikeThisQuery) booleanClause.getQuery();
+            assertThat(boolClauses[i].getOccur(), is(BooleanClause.Occur.SHOULD));
+            assertThat(boolClauses[i].getQuery(), instanceOf(MoreLikeThisQuery.class));
+            MoreLikeThisQuery mltQuery = (MoreLikeThisQuery) boolClauses[i].getQuery();
             assertThat(mltQuery.getLikeText(), is(likeTexts.get(i).text));
             assertThat(mltQuery.getMoreLikeFields()[0], equalTo(likeTexts.get(i).field));
         }
+
+        // check last clause is for 'like_text'
+        BooleanClause boolClause = boolClauses[boolClauses.length - 1];
+        assertThat(boolClause.getOccur(), is(BooleanClause.Occur.SHOULD));
+        assertThat(boolClause.getQuery(), instanceOf(MoreLikeThisQuery.class));
+        MoreLikeThisQuery mltQuery = (MoreLikeThisQuery) boolClause.getQuery();
+        assertArrayEquals("Not the same more like this 'fields'", new String[] {"name.first", "name.last"}, mltQuery.getMoreLikeFields());
+        assertThat(mltQuery.getLikeText(), equalTo("Apache Lucene"));
     }
 
     private static class MockMoreLikeThisFetchService extends MoreLikeThisFetchService {

+ 1 - 0
src/test/java/org/elasticsearch/index/query/mlt-ids.json

@@ -1,6 +1,7 @@
 {
     more_like_this:{
         "fields" : ["name.first", "name.last"],
+        "like_text": "Apache Lucene",
         "docs" : [
         {
             "_index" : "test",