Skip to content

Commit

Permalink
- Fixed boosting per field with multi_match query.
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnvg committed Sep 12, 2012
1 parent fbd352b commit b6a9bd9
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
MatchQuery.Type type = MatchQuery.Type.BOOLEAN;
MultiMatchQuery multiMatchQuery = new MultiMatchQuery(parseContext);
String minimumShouldMatch = null;
List<String> fieldNames = Lists.newArrayList();
Map<String, Float> fieldNameToBoost = Maps.newHashMap();
Map<String, Float> fieldNameWithBoosts = Maps.newHashMap();

XContentParser.Token token;
String currentFieldName = null;
Expand All @@ -75,7 +74,7 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
if ("fields".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
String fField = null;
float fBoost = -1;
Float fBoost = null;
char[] fieldText = parser.textCharacters();
int end = parser.textOffset() + parser.textLength();
for (int i = parser.textOffset(); i < end; i++) {
Expand All @@ -92,16 +91,10 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars

if (Regex.isSimpleMatchPattern(fField)) {
for (String field : parseContext.mapperService().simpleMatchToIndexNames(fField)) {
fieldNames.add(field);
if (fBoost != -1) {
fieldNameToBoost.put(field, fBoost);
}
fieldNameWithBoosts.put(field, fBoost);
}
} else {
fieldNames.add(fField);
if (fBoost != -1) {
fieldNameToBoost.put(fField, fBoost);
}
fieldNameWithBoosts.put(fField, fBoost);
}
}
} else {
Expand Down Expand Up @@ -166,11 +159,11 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
throw new QueryParsingException(parseContext.index(), "No text specified for match_all query");
}

if (fieldNames.isEmpty()) {
if (fieldNameWithBoosts.isEmpty()) {
throw new QueryParsingException(parseContext.index(), "No fields specified for match_all query");
}

Query query = multiMatchQuery.parse(type, fieldNames, text);
Query query = multiMatchQuery.parse(type, fieldNameWithBoosts, text);
if (query == null) {
return null;
}
Expand Down
25 changes: 21 additions & 4 deletions src/main/java/org/elasticsearch/index/search/MultiMatchQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.elasticsearch.index.query.QueryParseContext;

import java.util.List;
import java.util.Map;

public class MultiMatchQuery extends MatchQuery {

Expand All @@ -44,16 +45,28 @@ public MultiMatchQuery(QueryParseContext parseContext) {
super(parseContext);
}

public Query parse(Type type, List<String> fieldNames, String text) {
public Query parse(Type type, Map<String, Float> fieldNames, String text) {
if (fieldNames.size() == 1) {
return parse(type, fieldNames.get(0), text);
Map.Entry<String, Float> fieldBoost = fieldNames.entrySet().iterator().next();
Float boostValue = fieldBoost.getValue();
if (boostValue == null) {
return parse(type, fieldBoost.getKey(), text);
} else {
Query query = parse(type, fieldBoost.getKey(), text);
query.setBoost(boostValue);
return query;
}
}

if (useDisMax) {
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(tieBreaker);
boolean clauseAdded = false;
for (String fieldName : fieldNames) {
for (String fieldName : fieldNames.keySet()) {
Query query = parse(type, fieldName, text);
Float boostValue = fieldNames.get(fieldName);
if (boostValue != null) {
query.setBoost(boostValue);
}
if (query != null) {
clauseAdded = true;
disMaxQuery.add(query);
Expand All @@ -62,8 +75,12 @@ public Query parse(Type type, List<String> fieldNames, String text) {
return clauseAdded ? disMaxQuery : null;
} else {
BooleanQuery booleanQuery = new BooleanQuery();
for (String fieldName : fieldNames) {
for (String fieldName : fieldNames.keySet()) {
Query query = parse(type, fieldName, text);
Float boostValue = fieldNames.get(fieldName);
if (boostValue != null) {
query.setBoost(boostValue);
}
if (query != null) {
booleanQuery.add(query, BooleanClause.Occur.SHOULD);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,9 @@ public void testMultiMatchQuery() throws Exception {

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").execute().actionGet();
client.prepareIndex("test", "type1", "2").setSource("field1", "value2", "field2", "value5").execute().actionGet();
client.prepareIndex("test", "type1", "3").setSource("field1", "value3", "field2", "value6").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");
Expand Down Expand Up @@ -442,11 +442,21 @@ public void testMultiMatchQuery() throws Exception {
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()));

// Test lenient
client.prepareIndex("test", "type1", "3").setSource("field1", "value7", "field2", "value8", "field3", 5).execute().actionGet();
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", "field3");
builder = QueryBuilders.multiMatchQuery("value1", "field1", "field2", "field4");
try {
client.prepareSearch()
.setQuery(builder)
Expand Down

0 comments on commit b6a9bd9

Please sign in to comment.