From 927303e7a9cf427b352290aa8bb199bfc9606b7c Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Wed, 2 Mar 2016 10:51:47 +0100 Subject: [PATCH] Change the field mapping index time boost into a query time boost. Index time boost will still be applied for indices created before 5.0.0. --- .../index/mapper/DocumentParser.java | 19 ---- .../index/mapper/FieldMapper.java | 3 +- .../index/mapper/MappedFieldType.java | 9 +- .../index/mapper/ParseContext.java | 27 ------ .../index/mapper/core/ByteFieldMapper.java | 4 +- .../index/mapper/core/DateFieldMapper.java | 4 +- .../index/mapper/core/DoubleFieldMapper.java | 4 +- .../index/mapper/core/FloatFieldMapper.java | 4 +- .../index/mapper/core/IntegerFieldMapper.java | 4 +- .../index/mapper/core/LongFieldMapper.java | 4 +- .../index/mapper/core/ShortFieldMapper.java | 4 +- .../index/mapper/core/StringFieldMapper.java | 4 +- .../index/mapper/geo/GeoShapeFieldMapper.java | 4 +- .../index/mapper/ip/IpFieldMapper.java | 5 +- .../mapper/boost/CustomBoostMappingTests.java | 89 ++++++++++++++++++ .../mapper/boost/FieldLevelBoostTests.java | 92 +++++++++++++++++++ .../mapping/fields/all-field.asciidoc | 2 +- docs/reference/mapping/params.asciidoc | 2 +- docs/reference/mapping/params/boost.asciidoc | 57 +++++++++--- docs/reference/mapping/params/norms.asciidoc | 6 +- docs/reference/mapping/types/boolean.asciidoc | 4 +- docs/reference/mapping/types/date.asciidoc | 4 +- docs/reference/mapping/types/ip.asciidoc | 4 +- docs/reference/mapping/types/numeric.asciidoc | 4 +- docs/reference/mapping/types/string.asciidoc | 4 +- .../mapping/types/token-count.asciidoc | 4 +- docs/reference/redirects.asciidoc | 5 + docs/reference/search/request-body.asciidoc | 2 +- 28 files changed, 286 insertions(+), 92 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java index 78b05117104..2694b64783b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java @@ -98,7 +98,6 @@ class DocumentParser implements Closeable { } reverseOrder(context); - applyDocBoost(context); ParsedDocument doc = parsedDocument(source, context, update(context, mapping)); // reset the context to free up memory @@ -186,24 +185,6 @@ class DocumentParser implements Closeable { } } - private static void applyDocBoost(ParseContext.InternalParseContext context) { - // apply doc boost - if (context.docBoost() != 1.0f) { - Set encounteredFields = new HashSet<>(); - for (ParseContext.Document doc : context.docs()) { - encounteredFields.clear(); - for (IndexableField field : doc) { - if (field.fieldType().indexOptions() != IndexOptions.NONE && !field.fieldType().omitNorms()) { - if (!encounteredFields.contains(field.name())) { - ((Field) field).setBoost(context.docBoost() * field.boost()); - encounteredFields.add(field.name()); - } - } - } - } - } - } - private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.InternalParseContext context, Mapping update) { return new ParsedDocument( context.uid(), diff --git a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index e40d711cb6c..dba1355a395 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -300,7 +300,8 @@ public abstract class FieldMapper extends Mapper implements Cloneable { for (Field field : fields) { if (!customBoost() // don't set boosts eg. on dv fields - && field.fieldType().indexOptions() != IndexOptions.NONE) { + && field.fieldType().indexOptions() != IndexOptions.NONE + && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { field.setBoost(fieldType().boost()); } context.doc().add(field); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index f030ebed7ac..10b165ff4c5 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -32,7 +32,9 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.RegexpQuery; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermRangeQuery; +import org.apache.lucene.search.BoostQuery; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.Version; import org.elasticsearch.action.fieldstats.FieldStats; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; @@ -398,7 +400,12 @@ public abstract class MappedFieldType extends FieldType { } public Query termQuery(Object value, @Nullable QueryShardContext context) { - return new TermQuery(createTerm(value)); + TermQuery query = new TermQuery(createTerm(value)); + if (boost == 1f || + (context != null && context.indexVersionCreated().before(Version.V_5_0_0))) { + return query; + } + return new BoostQuery(query, boost); } public Query termsQuery(List values, @Nullable QueryShardContext context) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java index 938dd778b0e..5bd840cf543 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ParseContext.java @@ -321,16 +321,6 @@ public abstract class ParseContext { return in.externalValue(); } - @Override - public float docBoost() { - return in.docBoost(); - } - - @Override - public void docBoost(float docBoost) { - in.docBoost(docBoost); - } - @Override public StringBuilder stringBuilder() { return in.stringBuilder(); @@ -375,8 +365,6 @@ public abstract class ParseContext { private AllEntries allEntries = new AllEntries(); - private float docBoost = 1.0f; - private Mapper dynamicMappingsUpdate = null; public InternalParseContext(@Nullable Settings indexSettings, DocumentMapperParser docMapperParser, DocumentMapper docMapper, ContentPath path) { @@ -402,7 +390,6 @@ public abstract class ParseContext { this.source = source == null ? null : sourceToParse.source(); this.path.reset(); this.allEntries = new AllEntries(); - this.docBoost = 1.0f; this.dynamicMappingsUpdate = null; } @@ -534,16 +521,6 @@ public abstract class ParseContext { return this.allEntries; } - @Override - public float docBoost() { - return this.docBoost; - } - - @Override - public void docBoost(float docBoost) { - this.docBoost = docBoost; - } - /** * A string builder that can be used to construct complex names for example. * Its better to reuse the. @@ -759,10 +736,6 @@ public abstract class ParseContext { return clazz.cast(externalValue()); } - public abstract float docBoost(); - - public abstract void docBoost(float docBoost); - /** * A string builder that can be used to construct complex names for example. * Its better to reuse the. diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java index 5944bb7fb1c..29081c6c913 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java @@ -285,7 +285,9 @@ public class ByteFieldMapper extends NumberFieldMapper { } if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomByteNumericField field = new CustomByteNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 7975228ec0b..be83f0175c2 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -513,7 +513,9 @@ public class DateFieldMapper extends NumberFieldMapper { if (value != null) { if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomLongNumericField field = new CustomLongNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java index cab949c19f5..7d33d09cd99 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java @@ -278,7 +278,9 @@ public class DoubleFieldMapper extends NumberFieldMapper { if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomDoubleNumericField field = new CustomDoubleNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java index 9c3715fcb47..85c5b619bf1 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java @@ -290,7 +290,9 @@ public class FloatFieldMapper extends NumberFieldMapper { if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomFloatNumericField field = new CustomFloatNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java index 3c30e1b644f..7de62510415 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java @@ -298,7 +298,9 @@ public class IntegerFieldMapper extends NumberFieldMapper { protected void addIntegerFields(ParseContext context, List fields, int value, float boost) { if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomIntegerNumericField field = new CustomIntegerNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java index 3f774e90a10..0e9592fd72e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java @@ -282,7 +282,9 @@ public class LongFieldMapper extends NumberFieldMapper { } if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomLongNumericField field = new CustomLongNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java index 0ced9d39b89..027f0b1b40b 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java @@ -290,7 +290,9 @@ public class ShortFieldMapper extends NumberFieldMapper { } if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomShortNumericField field = new CustomShortNumericField(value, fieldType()); - field.setBoost(boost); + if (boost != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(boost); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java index 199de497c5c..eda7b7fc87f 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/StringFieldMapper.java @@ -317,7 +317,9 @@ public class StringFieldMapper extends FieldMapper implements AllFieldMapper.Inc if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { Field field = new Field(fieldType().name(), valueAndBoost.value(), fieldType()); - field.setBoost(valueAndBoost.boost()); + if (valueAndBoost.boost() != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(valueAndBoost.boost()); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java index bf699afa514..e90fdae0c47 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/geo/GeoShapeFieldMapper.java @@ -30,6 +30,7 @@ import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; import org.apache.lucene.spatial.prefix.tree.PackedQuadPrefixTree; import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree; import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; +import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; import org.elasticsearch.common.Strings; import org.elasticsearch.common.geo.GeoUtils; @@ -452,7 +453,8 @@ public class GeoShapeFieldMapper extends FieldMapper { return null; } for (Field field : fields) { - if (!customBoost()) { + if (!customBoost() && + fieldType.boost() != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { field.setBoost(fieldType().boost()); } context.doc().add(field); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java index 9b8630040ff..18929bfd833 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java @@ -27,6 +27,7 @@ import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.NumericUtils; +import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Numbers; @@ -305,7 +306,9 @@ public class IpFieldMapper extends NumberFieldMapper { final long value = ipToLong(ipAsString); if (fieldType().indexOptions() != IndexOptions.NONE || fieldType().stored()) { CustomLongNumericField field = new CustomLongNumericField(value, fieldType()); - field.setBoost(fieldType().boost()); + if (fieldType.boost() != 1f && Version.indexCreated(context.indexSettings()).before(Version.V_5_0_0)) { + field.setBoost(fieldType().boost()); + } fields.add(field); } if (fieldType().hasDocValues()) { diff --git a/core/src/test/java/org/elasticsearch/index/mapper/boost/CustomBoostMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/boost/CustomBoostMappingTests.java index 51eef673c5f..91a0ca15cd4 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/boost/CustomBoostMappingTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/boost/CustomBoostMappingTests.java @@ -19,13 +19,18 @@ package org.elasticsearch.index.mapper.boost; +import org.apache.lucene.search.BoostQuery; +import org.apache.lucene.search.TermQuery; import org.elasticsearch.Version; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.IndexService; +import org.elasticsearch.index.mapper.DocumentFieldMappers; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESSingleNodeTestCase; import org.elasticsearch.test.InternalSettingsPlugin; @@ -33,6 +38,7 @@ import org.elasticsearch.test.InternalSettingsPlugin; import java.util.Collection; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.instanceOf; public class CustomBoostMappingTests extends ESSingleNodeTestCase { @@ -77,4 +83,87 @@ public class CustomBoostMappingTests extends ESSingleNodeTestCase { assertThat(doc.rootDoc().getField("f_field").boost(), equalTo(8.0f)); assertThat(doc.rootDoc().getField("date_field").boost(), equalTo(9.0f)); } + + public void testBackCompatFieldMappingBoostValues() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties") + .startObject("s_field").field("type", "keyword").field("boost", 2.0f).endObject() + .startObject("l_field").field("type", "long").field("boost", 3.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("i_field").field("type", "integer").field("boost", 4.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("sh_field").field("type", "short").field("boost", 5.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("b_field").field("type", "byte").field("boost", 6.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("d_field").field("type", "double").field("boost", 7.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("f_field").field("type", "float").field("boost", 8.0f).startObject("norms").field("enabled", true).endObject().endObject() + .startObject("date_field").field("type", "date").field("boost", 9.0f).startObject("norms").field("enabled", true).endObject().endObject() + .endObject().endObject().endObject().string(); + + { + IndexService indexService = createIndex("test", BW_SETTINGS); + QueryShardContext context = indexService.newQueryShardContext(); + DocumentMapper mapper = indexService.mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); + DocumentFieldMappers fieldMappers = mapper.mappers(); + assertThat(fieldMappers.getMapper("s_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("l_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("i_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("sh_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("b_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("d_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("f_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + assertThat(fieldMappers.getMapper("date_field").fieldType().termQuery("0", context), instanceOf(TermQuery.class)); + + ParsedDocument doc = mapper.parse("test", "type", "1", XContentFactory.jsonBuilder().startObject() + .field("s_field", "s_value") + .field("l_field", 1L) + .field("i_field", 1) + .field("sh_field", 1) + .field("b_field", 1) + .field("d_field", 1) + .field("f_field", 1) + .field("date_field", "20100101") + .endObject().bytes()); + + assertThat(doc.rootDoc().getField("s_field").boost(), equalTo(2.0f)); + assertThat(doc.rootDoc().getField("l_field").boost(), equalTo(3.0f)); + assertThat(doc.rootDoc().getField("i_field").boost(), equalTo(4.0f)); + assertThat(doc.rootDoc().getField("sh_field").boost(), equalTo(5.0f)); + assertThat(doc.rootDoc().getField("b_field").boost(), equalTo(6.0f)); + assertThat(doc.rootDoc().getField("d_field").boost(), equalTo(7.0f)); + assertThat(doc.rootDoc().getField("f_field").boost(), equalTo(8.0f)); + assertThat(doc.rootDoc().getField("date_field").boost(), equalTo(9.0f)); + } + + { + IndexService indexService = createIndex("text"); + QueryShardContext context = indexService.newQueryShardContext(); + DocumentMapper mapper = indexService.mapperService().documentMapperParser().parse("type", new CompressedXContent(mapping)); + DocumentFieldMappers fieldMappers = mapper.mappers(); + assertThat(fieldMappers.getMapper("s_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("l_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("i_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("sh_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("b_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("d_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("f_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + assertThat(fieldMappers.getMapper("date_field").fieldType().termQuery("0", context), instanceOf(BoostQuery.class)); + + ParsedDocument doc = mapper.parse("test", "type", "1", XContentFactory.jsonBuilder().startObject() + .field("s_field", "s_value") + .field("l_field", 1L) + .field("i_field", 1) + .field("sh_field", 1) + .field("b_field", 1) + .field("d_field", 1) + .field("f_field", 1) + .field("date_field", "20100101") + .endObject().bytes()); + + assertThat(doc.rootDoc().getField("s_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("l_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("i_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("sh_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("b_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("d_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("f_field").boost(), equalTo(1f)); + assertThat(doc.rootDoc().getField("date_field").boost(), equalTo(1f)); + } + } } diff --git a/core/src/test/java/org/elasticsearch/index/mapper/boost/FieldLevelBoostTests.java b/core/src/test/java/org/elasticsearch/index/mapper/boost/FieldLevelBoostTests.java index 6b83ae51385..b1fde6bdd67 100644 --- a/core/src/test/java/org/elasticsearch/index/mapper/boost/FieldLevelBoostTests.java +++ b/core/src/test/java/org/elasticsearch/index/mapper/boost/FieldLevelBoostTests.java @@ -36,6 +36,7 @@ import org.elasticsearch.test.InternalSettingsPlugin; import java.util.Collection; import static org.hamcrest.Matchers.closeTo; +import static org.hamcrest.Matchers.equalTo; /** */ @@ -98,6 +99,97 @@ public class FieldLevelBoostTests extends ESSingleNodeTestCase { assertThat((double) f.boost(), closeTo(9.0, 0.001)); } + public void testBackCompatFieldLevelMappingBoost() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("person").startObject("properties") + .startObject("str_field").field("type", "keyword").field("boost", "2.0").endObject() + .startObject("int_field").field("type", "integer").field("boost", "3.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("byte_field").field("type", "byte").field("boost", "4.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("date_field").field("type", "date").field("boost", "5.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("double_field").field("type", "double").field("boost", "6.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("float_field").field("type", "float").field("boost", "7.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("long_field").field("type", "long").field("boost", "8.0").startObject("norms").field("enabled", true).endObject().endObject() + .startObject("short_field").field("type", "short").field("boost", "9.0").startObject("norms").field("enabled", true).endObject().endObject() + .string(); + + { + DocumentMapper docMapper = createIndex("test", BW_SETTINGS).mapperService().documentMapperParser().parse("person", new CompressedXContent(mapping)); + BytesReference json = XContentFactory.jsonBuilder().startObject() + .field("str_field", "some name") + .field("int_field", 10) + .field("byte_field", 20) + .field("date_field", "2012-01-10") + .field("double_field", 30.0) + .field("float_field", 40.0) + .field("long_field", 50) + .field("short_field", 60) + .bytes(); + Document doc = docMapper.parse("test", "person", "1", json).rootDoc(); + + IndexableField f = doc.getField("str_field"); + assertThat((double) f.boost(), closeTo(2.0, 0.001)); + + f = doc.getField("int_field"); + assertThat((double) f.boost(), closeTo(3.0, 0.001)); + + f = doc.getField("byte_field"); + assertThat((double) f.boost(), closeTo(4.0, 0.001)); + + f = doc.getField("date_field"); + assertThat((double) f.boost(), closeTo(5.0, 0.001)); + + f = doc.getField("double_field"); + assertThat((double) f.boost(), closeTo(6.0, 0.001)); + + f = doc.getField("float_field"); + assertThat((double) f.boost(), closeTo(7.0, 0.001)); + + f = doc.getField("long_field"); + assertThat((double) f.boost(), closeTo(8.0, 0.001)); + + f = doc.getField("short_field"); + assertThat((double) f.boost(), closeTo(9.0, 0.001)); + } + + { + DocumentMapper docMapper = createIndex("test2").mapperService().documentMapperParser().parse("person", new CompressedXContent(mapping)); + BytesReference json = XContentFactory.jsonBuilder().startObject() + .field("str_field", "some name") + .field("int_field", 10) + .field("byte_field", 20) + .field("date_field", "2012-01-10") + .field("double_field", 30.0) + .field("float_field", 40.0) + .field("long_field", 50) + .field("short_field", 60) + .bytes(); + Document doc = docMapper.parse("test", "person", "1", json).rootDoc(); + + IndexableField f = doc.getField("str_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("int_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("byte_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("date_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("double_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("float_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("long_field"); + assertThat(f.boost(), equalTo(1f)); + + f = doc.getField("short_field"); + assertThat(f.boost(), equalTo(1f)); + } + } + public void testBackCompatInvalidFieldLevelBoost() throws Exception { String mapping = XContentFactory.jsonBuilder().startObject().startObject("person").startObject("properties") .startObject("str_field").field("type", "string").endObject() diff --git a/docs/reference/mapping/fields/all-field.asciidoc b/docs/reference/mapping/fields/all-field.asciidoc index e206dcd125f..ae52fc1d0d1 100644 --- a/docs/reference/mapping/fields/all-field.asciidoc +++ b/docs/reference/mapping/fields/all-field.asciidoc @@ -161,7 +161,7 @@ Individual fields can be included or excluded from the `_all` field with the [[all-field-and-boosting]] ==== Index boosting and the `_all` field -Individual fields can be _boosted_ at index time, with the <> +Individual fields can be _boosted_ at index time, with the <> parameter. The `_all` field takes these boosts into account: [source,js] diff --git a/docs/reference/mapping/params.asciidoc b/docs/reference/mapping/params.asciidoc index 719fa00acf3..4071c383ba1 100644 --- a/docs/reference/mapping/params.asciidoc +++ b/docs/reference/mapping/params.asciidoc @@ -8,7 +8,7 @@ parameters that are used by <>: The following mapping parameters are common to some or all field datatypes: * <> -* <> +* <> * <> * <> * <> diff --git a/docs/reference/mapping/params/boost.asciidoc b/docs/reference/mapping/params/boost.asciidoc index b92e081ca72..22c0e2e69ea 100644 --- a/docs/reference/mapping/params/boost.asciidoc +++ b/docs/reference/mapping/params/boost.asciidoc @@ -1,8 +1,8 @@ -[[index-boost]] +[[mapping-boost]] === `boost` -Individual fields can be _boosted_ -- count more towards the relevance score --- at index time, with the `boost` parameter as follows: +Individual fields can be _boosted_ automatically -- count more towards the relevance score +-- at query time, with the `boost` parameter as follows: [source,js] -------------------------------------------------- @@ -28,10 +28,45 @@ PUT my_index <1> Matches on the `title` field will have twice the weight as those on the `content` field, which has the default `boost` of `1.0`. -Note that a `title` field will usually be shorter than a `content` field. The -default relevance calculation takes field length into account, so a short -`title` field will have a higher natural boost than a long `content` field. +NOTE: The boost is applied only for term queries (prefix, range and fuzzy queries are not _boosted_). +You can achieve the same effect by using the boost parameter directly in the query, for instance the following query (with field time boost): + +[source,js] +-------------------------------------------------- +{ + "match" : { + "title": { + "query": "quick brown fox" + } + } +} +-------------------------------------------------- + +is equivalent to: + +[source,js] +-------------------------------------------------- +{ + "match" : { + "title": { + "query": "quick brown fox", + "boost": 2 + } + } +} +-------------------------------------------------- +// AUTOSENSE + + +The boost is also applied when it is copied with the +value in the <> field. This means that, when +querying the `_all` field, words that originated from the `title` field will +have a higher score than words that originated in the `content` field. +This functionality comes at a cost: queries on the `_all` field are slower +when field boosting is used. + +deprecated[5.0.0, index time boost is deprecated. Instead, the field mapping boost is applied at query time. For indices created before 5.0.0 the boost will still be applied at index time.] [WARNING] .Why index time boosting is a bad idea ================================================== @@ -48,12 +83,4 @@ We advise against using index time boosting for the following reasons: byte. This reduces the resolution of the field length normalization factor which can lead to lower quality relevance calculations. -================================================== - -The only advantage that index time boosting has is that it is copied with the -value into the <> field. This means that, when -querying the `_all` field, words that originated from the `title` field will -have a higher score than words that originated in the `content` field. -This functionality comes at a cost: queries on the `_all` field are slower -when index-time boosting is used. - +================================================== \ No newline at end of file diff --git a/docs/reference/mapping/params/norms.asciidoc b/docs/reference/mapping/params/norms.asciidoc index 5878d88f5da..f83f93caf56 100644 --- a/docs/reference/mapping/params/norms.asciidoc +++ b/docs/reference/mapping/params/norms.asciidoc @@ -1,10 +1,8 @@ [[norms]] === `norms` -Norms store various normalization factors -- a number to represent the -relative field length and the <> setting -- -that are later used at query time in order to compute the score of a document -relatively to a query. +Norms store various normalization factors that are later used at query time +in order to compute the score of a document relatively to a query. Although useful for scoring, norms also require quite a lot of memory (typically in the order of one byte per document per field in your index, even diff --git a/docs/reference/mapping/types/boolean.asciidoc b/docs/reference/mapping/types/boolean.asciidoc index 200b1c7b8d8..65f03942fc2 100644 --- a/docs/reference/mapping/types/boolean.asciidoc +++ b/docs/reference/mapping/types/boolean.asciidoc @@ -91,9 +91,9 @@ The following parameters are accepted by `boolean` fields: [horizontal] -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/mapping/types/date.asciidoc b/docs/reference/mapping/types/date.asciidoc index 3ee123678b8..46fa599ef28 100644 --- a/docs/reference/mapping/types/date.asciidoc +++ b/docs/reference/mapping/types/date.asciidoc @@ -90,9 +90,9 @@ The following parameters are accepted by `date` fields: [horizontal] -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/mapping/types/ip.asciidoc b/docs/reference/mapping/types/ip.asciidoc index 49656f99013..007a64e3f71 100644 --- a/docs/reference/mapping/types/ip.asciidoc +++ b/docs/reference/mapping/types/ip.asciidoc @@ -47,9 +47,9 @@ The following parameters are accepted by `ip` fields: [horizontal] -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/mapping/types/numeric.asciidoc b/docs/reference/mapping/types/numeric.asciidoc index 4a4fd800152..ffe3bf057f4 100644 --- a/docs/reference/mapping/types/numeric.asciidoc +++ b/docs/reference/mapping/types/numeric.asciidoc @@ -45,9 +45,9 @@ The following parameters are accepted by numeric types: Try to convert strings to numbers and truncate fractions for integers. Accepts `true` (default) and `false`. -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/mapping/types/string.asciidoc b/docs/reference/mapping/types/string.asciidoc index 66488c40fd1..6ff78aa4732 100644 --- a/docs/reference/mapping/types/string.asciidoc +++ b/docs/reference/mapping/types/string.asciidoc @@ -75,9 +75,9 @@ The following parameters are accepted by `string` fields: Defaults to the default index analyzer, or the <>. -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/mapping/types/token-count.asciidoc b/docs/reference/mapping/types/token-count.asciidoc index ec02a647a6f..ca2ed6f0428 100644 --- a/docs/reference/mapping/types/token-count.asciidoc +++ b/docs/reference/mapping/types/token-count.asciidoc @@ -68,9 +68,9 @@ The following parameters are accepted by `token_count` fields: value. Required. For best performance, use an analyzer without token filters. -<>:: +<>:: - Field-level index time boosting. Accepts a floating point number, defaults + Mapping field-level query time boosting. Accepts a floating point number, defaults to `1.0`. <>:: diff --git a/docs/reference/redirects.asciidoc b/docs/reference/redirects.asciidoc index 322c9e7308e..2a92e90e608 100644 --- a/docs/reference/redirects.asciidoc +++ b/docs/reference/redirects.asciidoc @@ -449,3 +449,8 @@ The docs for the `nested` field datatype have moved to <>. Warmers have been removed. There have been significant improvements to the index that make warmers not necessary anymore. + +[role="exclude",id="index-boost"] +=== Index time boosting + +The index time boost mapping has been replaced with query time boost (see <>). diff --git a/docs/reference/search/request-body.asciidoc b/docs/reference/search/request-body.asciidoc index 8207c6577fe..62b1af72ab2 100644 --- a/docs/reference/search/request-body.asciidoc +++ b/docs/reference/search/request-body.asciidoc @@ -165,7 +165,7 @@ include::request/explain.asciidoc[] include::request/version.asciidoc[] -include::request/index-boost.asciidoc[] +include::request/mapping-boost.asciidoc[] include::request/min-score.asciidoc[]