Skip to content

Commit

Permalink
Allow to disable norms on an existing field.
Browse files Browse the repository at this point in the history
Close #4813
  • Loading branch information
jpountz committed Mar 25, 2014
1 parent f2b5b67 commit cd5bcda
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
22 changes: 22 additions & 0 deletions docs/reference/mapping/types/core-types.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ all.

|`norms.enabled` |Boolean value if norms should be enabled or not. Defaults
to `true` for `analyzed` fields, and to `false` for `not_analyzed` fields.
See the <<norms,section about norms>>.

|`norms.loading` |Describes how norms should be loaded, possible values are
`eager` and `lazy` (default). It is possible to change the default value to
Expand Down Expand Up @@ -166,6 +167,27 @@ Otherwise, the structure would interpret "message" as a value of type
the real string content that should eventually be indexed. The `_boost`
(or `boost`) key specifies the per field document boost (here 2.0).

[float]
[[norms]]
===== Norms

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 for documents that don't have this specific field). As a consequence, if
you don't need scoring on a specific field, it is highly recommended to disable
norms on it. In particular, this is the case for fields that are used solely
for filtering or aggregations.

In case you would like to disable norms after the fact, it is possible to do so
by using the <<indices-put-mapping,PUT mapping API>>. Please however note that
norms won't be removed instantly, but as your index will receive new insertions
or updates, and segments get merged. Any score computation on a field that got
norms removed might return inconsistent results since some documents won't have
norms anymore while other documents might still have norms.

[float]
[[number]]
==== Number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ protected List<Field> initialValue() {

protected final Names names;
protected float boost;
protected final FieldType fieldType;
protected FieldType fieldType;
private final boolean docValues;
protected final NamedAnalyzer indexAnalyzer;
protected NamedAnalyzer searchAnalyzer;
Expand Down Expand Up @@ -579,8 +579,8 @@ public void merge(Mapper mergeWith, MergeContext mergeContext) throws MergeMappi
// when the doc_values field data format is configured
mergeContext.addConflict("mapper [" + names.fullName() + "] has different " + TypeParsers.DOC_VALUES + " values");
}
if (this.fieldType().omitNorms() != fieldMergeWith.fieldType.omitNorms()) {
mergeContext.addConflict("mapper [" + names.fullName() + "] has different `norms.enabled` values");
if (this.fieldType().omitNorms() && !fieldMergeWith.fieldType.omitNorms()) {
mergeContext.addConflict("mapper [" + names.fullName() + "] cannot enable norms (`norms.enabled`)");
}
if (this.fieldType().tokenized() != fieldMergeWith.fieldType().tokenized()) {
mergeContext.addConflict("mapper [" + names.fullName() + "] has different tokenize values");
Expand Down Expand Up @@ -620,6 +620,9 @@ public void merge(Mapper mergeWith, MergeContext mergeContext) throws MergeMappi

if (!mergeContext.mergeFlags().simulate()) {
// apply changeable values
this.fieldType = new FieldType(this.fieldType);
this.fieldType.setOmitNorms(fieldMergeWith.fieldType.omitNorms());
this.fieldType.freeze();
this.boost = fieldMergeWith.boost;
this.normsLoading = fieldMergeWith.normsLoading;
this.copyTo = fieldMergeWith.copyTo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@
import org.apache.lucene.index.FieldInfo.DocValuesType;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.IndexableFieldType;
import org.apache.mahout.math.Arrays;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.DocumentMapper.MergeFlags;
import org.elasticsearch.index.mapper.DocumentMapper.MergeResult;
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
import org.elasticsearch.index.mapper.ParseContext.Document;
import org.elasticsearch.index.mapper.core.StringFieldMapper;
Expand Down Expand Up @@ -319,4 +322,45 @@ public static DocValuesType docValuesType(Document document, String fieldName) {
return null;
}

@Test
public void testDisableNorms() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field").field("type", "string").endObject().endObject()
.endObject().endObject().string();

DocumentMapper defaultMapper = MapperTestUtils.newParser().parse(mapping);

ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field", "1234")
.endObject()
.bytes());

IndexableFieldType fieldType = doc.rootDoc().getField("field").fieldType();
assertEquals(false, fieldType.omitNorms());

String updatedMapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field").field("type", "string").startObject("norms").field("enabled", false).endObject()
.endObject().endObject().endObject().endObject().string();
MergeResult mergeResult = defaultMapper.merge(MapperTestUtils.newParser().parse(updatedMapping), MergeFlags.mergeFlags().simulate(false));
assertFalse(Arrays.toString(mergeResult.conflicts()), mergeResult.hasConflicts());

doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("field", "1234")
.endObject()
.bytes());

fieldType = doc.rootDoc().getField("field").fieldType();
assertEquals(true, fieldType.omitNorms());

updatedMapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("field").field("type", "string").startObject("norms").field("enabled", true).endObject()
.endObject().endObject().endObject().endObject().string();
mergeResult = defaultMapper.merge(MapperTestUtils.newParser().parse(updatedMapping), MergeFlags.mergeFlags());
assertTrue(mergeResult.hasConflicts());
assertEquals(1, mergeResult.conflicts().length);
assertTrue(mergeResult.conflicts()[0].contains("cannot enable norms"));
}

}

0 comments on commit cd5bcda

Please sign in to comment.