diff --git a/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java index 883d7838aa3..67bf93d9888 100644 --- a/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/MultiMatchQueryBuilder.java @@ -19,6 +19,9 @@ package org.elasticsearch.index.query; +import com.google.common.collect.Lists; +import gnu.trove.impl.Constants; +import gnu.trove.map.hash.TObjectFloatHashMap; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; @@ -34,6 +37,7 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl private final Object text; private final List fields; + private TObjectFloatHashMap fieldsBoosts; private MatchQueryBuilder.Type type; @@ -67,10 +71,31 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl * Constructs a new text query. */ public MultiMatchQueryBuilder(Object text, String... fields) { - this.fields = Arrays.asList(fields); + this.fields = Lists.newArrayList(); + this.fields.addAll(Arrays.asList(fields)); this.text = text; } + /** + * Adds a field to run the multi match against. + */ + public MultiMatchQueryBuilder field(String field) { + fields.add(field); + return this; + } + + /** + * Adds a field to run the multi match against with a specific boost. + */ + public MultiMatchQueryBuilder field(String field, float boost) { + fields.add(field); + if (fieldsBoosts == null) { + fieldsBoosts = new TObjectFloatHashMap(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, -1); + } + fieldsBoosts.put(field, boost); + return this; + } + /** * Sets the type of the text query. */ @@ -172,7 +197,18 @@ public class MultiMatchQueryBuilder extends BaseQueryBuilder implements Boostabl builder.startObject(MultiMatchQueryParser.NAME); builder.field("query", text); - builder.field("fields", fields); + builder.startArray("fields"); + for (String field : fields) { + float boost = -1; + if (fieldsBoosts != null) { + boost = fieldsBoosts.get(field); + } + if (boost != -1) { + field += "^" + boost; + } + builder.value(field); + } + builder.endArray(); if (type != null) { builder.field("type", type.toString().toLowerCase(Locale.ENGLISH)); diff --git a/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java b/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java index 4620c01f5b9..065a1dbc22e 100644 --- a/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java +++ b/src/test/java/org/elasticsearch/test/integration/search/query/SimpleQueryTests.java @@ -19,8 +19,6 @@ package org.elasticsearch.test.integration.search.query; -import org.elasticsearch.ElasticSearchException; -import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.search.SearchPhaseExecutionException; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; @@ -34,8 +32,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.index.query.FilterBuilders.*; @@ -43,7 +39,6 @@ import static org.elasticsearch.index.query.QueryBuilders.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.instanceOf; import static org.testng.Assert.fail; /** @@ -84,7 +79,7 @@ public class SimpleQueryTests extends AbstractNodesTests { SearchResponse searchResponse = client.prepareSearch().setQuery("{ \"term\" : { \"field1\" : \"value1_1\" }}").execute().actionGet(); assertThat(searchResponse.hits().totalHits(), equalTo(1l)); } - + @Test public void testIndexOptions() throws Exception { try { @@ -94,9 +89,9 @@ public class SimpleQueryTests extends AbstractNodesTests { } 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(); - + .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(); @@ -105,7 +100,7 @@ public class SimpleQueryTests extends AbstractNodesTests { SearchResponse actionGet = client.prepareSearch().setQuery("{ \"text_phrase\" : { \"field1\" : \"quick brown\", \"slop\" : \"2\" }}").execute().actionGet(); assertThat(actionGet.hits().totalHits(), equalTo(0l)); } - + @Test public void testOmitTermFreqsAndPositions() throws Exception { // backwards compat test! @@ -116,9 +111,9 @@ public class SimpleQueryTests extends AbstractNodesTests { } client.admin().indices().prepareCreate("test") - .addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("field1").field("omit_term_freq_and_positions", true).field("type", "string").endObject().endObject().endObject().endObject()) - .setSettings(ImmutableSettings.settingsBuilder().put("number_of_shards", 1)).execute().actionGet(); - + .addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("field1").field("omit_term_freq_and_positions", true).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(); @@ -452,6 +447,16 @@ public class SimpleQueryTests extends AbstractNodesTests { 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();