Mapping: non-string type field level boosting, closes #1097.

This commit is contained in:
kimchy 2011-07-06 22:35:29 +03:00
parent 4d3b623923
commit 9ef34f82ea
8 changed files with 308 additions and 31 deletions

View File

@ -175,8 +175,13 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
byte value; byte value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -191,7 +196,8 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
context.allEntries().addText(names.fullName(), Byte.toString(value), boost); context.allEntries().addText(names.fullName(), Byte.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -199,14 +205,38 @@ public class ByteFieldMapper extends NumberFieldMapper<Byte> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Byte objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = (byte) context.parser().shortValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = (byte) parser.shortValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = (byte) parser.shortValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomByteNumericField(this, value); CustomByteNumericField field = new CustomByteNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -215,9 +215,14 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
String dateAsString = null; String dateAsString = null;
long value = -1; Long value = null;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue instanceof Number) { if (externalValue instanceof Number) {
@ -229,18 +234,40 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
} }
} }
} else { } else {
XContentParser.Token token = context.parser().currentToken(); XContentParser parser = context.parser();
XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.VALUE_NULL) { if (token == XContentParser.Token.VALUE_NULL) {
dateAsString = nullValue; dateAsString = nullValue;
} else if (token == XContentParser.Token.VALUE_NUMBER) { } else if (token == XContentParser.Token.VALUE_NUMBER) {
value = context.parser().longValue(); value = parser.longValue();
} else if (token == XContentParser.Token.START_OBJECT) {
String currentFieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
dateAsString = context.parser().text(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (token == XContentParser.Token.VALUE_NULL) {
dateAsString = nullValue;
} else if (token == XContentParser.Token.VALUE_NUMBER) {
value = parser.longValue();
} else {
dateAsString = parser.text();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
} else {
dateAsString = parser.text();
} }
} }
if (value != -1) { if (value != null) {
return new LongFieldMapper.CustomLongNumericField(this, value); LongFieldMapper.CustomLongNumericField field = new LongFieldMapper.CustomLongNumericField(this, value);
field.setBoost(boost);
return field;
} }
if (dateAsString == null) { if (dateAsString == null) {
@ -251,7 +278,9 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
} }
value = parseStringValue(dateAsString); value = parseStringValue(dateAsString);
return new LongFieldMapper.CustomLongNumericField(this, value); LongFieldMapper.CustomLongNumericField field = new LongFieldMapper.CustomLongNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -171,8 +171,13 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
double value; double value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -187,7 +192,8 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
context.allEntries().addText(names.fullName(), Double.toString(value), boost); context.allEntries().addText(names.fullName(), Double.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -195,15 +201,39 @@ public class DoubleFieldMapper extends NumberFieldMapper<Double> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Double objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = context.parser().doubleValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = parser.doubleValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = parser.doubleValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomDoubleNumericField(this, value); CustomDoubleNumericField field = new CustomDoubleNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -170,8 +170,13 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
float value; float value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -186,7 +191,8 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
context.allEntries().addText(names.fullName(), Float.toString(value), boost); context.allEntries().addText(names.fullName(), Float.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -194,15 +200,39 @@ public class FloatFieldMapper extends NumberFieldMapper<Float> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Float objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = context.parser().floatValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = parser.floatValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = parser.floatValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomFloatNumericField(this, value); CustomFloatNumericField field = new CustomFloatNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -175,8 +175,13 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
int value; int value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -191,7 +196,8 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
context.allEntries().addText(names.fullName(), Integer.toString(value), boost); context.allEntries().addText(names.fullName(), Integer.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -199,15 +205,39 @@ public class IntegerFieldMapper extends NumberFieldMapper<Integer> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Integer objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = context.parser().intValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = parser.intValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = parser.intValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomIntegerNumericField(this, value); CustomIntegerNumericField field = new CustomIntegerNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -175,8 +175,13 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
long value; long value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -191,7 +196,8 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
context.allEntries().addText(names.fullName(), Long.toString(value), boost); context.allEntries().addText(names.fullName(), Long.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -199,14 +205,38 @@ public class LongFieldMapper extends NumberFieldMapper<Long> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Long objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = context.parser().longValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = parser.longValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = parser.longValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomLongNumericField(this, value); CustomLongNumericField field = new CustomLongNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -175,8 +175,13 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
includeLower, includeUpper); includeLower, includeUpper);
} }
@Override protected boolean customBoost() {
return true;
}
@Override protected Fieldable parseCreateField(ParseContext context) throws IOException { @Override protected Fieldable parseCreateField(ParseContext context) throws IOException {
short value; short value;
float boost = this.boost;
if (context.externalValueSet()) { if (context.externalValueSet()) {
Object externalValue = context.externalValue(); Object externalValue = context.externalValue();
if (externalValue == null) { if (externalValue == null) {
@ -191,7 +196,8 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
context.allEntries().addText(names.fullName(), Short.toString(value), boost); context.allEntries().addText(names.fullName(), Short.toString(value), boost);
} }
} else { } else {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) { XContentParser parser = context.parser();
if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) { if (nullValue == null) {
return null; return null;
} }
@ -199,14 +205,38 @@ public class ShortFieldMapper extends NumberFieldMapper<Short> {
if (nullValueAsString != null && (context.includeInAll(includeInAll))) { if (nullValueAsString != null && (context.includeInAll(includeInAll))) {
context.allEntries().addText(names.fullName(), nullValueAsString, boost); context.allEntries().addText(names.fullName(), nullValueAsString, boost);
} }
} else if (parser.currentToken() == XContentParser.Token.START_OBJECT) {
XContentParser.Token token;
String currentFieldName = null;
Short objValue = nullValue;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else { } else {
value = context.parser().shortValue(); if ("value".equals(currentFieldName) || "_value".equals(currentFieldName)) {
if (parser.currentToken() != XContentParser.Token.VALUE_NULL) {
objValue = parser.shortValue();
}
} else if ("boost".equals(currentFieldName) || "_boost".equals(currentFieldName)) {
boost = parser.floatValue();
}
}
}
if (objValue == null) {
// no value
return null;
}
value = objValue;
} else {
value = parser.shortValue();
if (context.includeInAll(includeInAll)) { if (context.includeInAll(includeInAll)) {
context.allEntries().addText(names.fullName(), context.parser().text(), boost); context.allEntries().addText(names.fullName(), parser.text(), boost);
} }
} }
} }
return new CustomShortNumericField(this, value); CustomShortNumericField field = new CustomShortNumericField(this, value);
field.setBoost(boost);
return field;
} }
@Override public FieldDataType fieldDataType() { @Override public FieldDataType fieldDataType() {

View File

@ -0,0 +1,68 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.mapper.boost;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MapperTests;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
@Test
public class CustomBoostMappingTests {
@Test public void testCustomBoostValues() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type").startObject("properties")
.startObject("s_field").field("type", "string").endObject()
.startObject("l_field").field("type", "long").endObject()
.startObject("i_field").field("type", "integer").endObject()
.startObject("sh_field").field("type", "short").endObject()
.startObject("b_field").field("type", "byte").endObject()
.startObject("d_field").field("type", "double").endObject()
.startObject("f_field").field("type", "float").endObject()
.startObject("date_field").field("type", "date").endObject()
.endObject().endObject().endObject().string();
DocumentMapper mapper = MapperTests.newParser().parse(mapping);
ParsedDocument doc = mapper.parse("type", "1", XContentFactory.jsonBuilder().startObject()
.startObject("s_field").field("value", "s_value").field("boost", 2.0f).endObject()
.startObject("l_field").field("value", 1l).field("boost", 3.0f).endObject()
.startObject("i_field").field("value", 1).field("boost", 4.0f).endObject()
.startObject("sh_field").field("value", 1).field("boost", 5.0f).endObject()
.startObject("b_field").field("value", 1).field("boost", 6.0f).endObject()
.startObject("d_field").field("value", 1).field("boost", 7.0f).endObject()
.startObject("f_field").field("value", 1).field("boost", 8.0f).endObject()
.startObject("date_field").field("value", "20100101").field("boost", 9.0f).endObject()
.endObject().copiedBytes());
assertThat(doc.masterDoc().getFieldable("s_field").getBoost(), equalTo(2.0f));
assertThat(doc.masterDoc().getFieldable("l_field").getBoost(), equalTo(3.0f));
assertThat(doc.masterDoc().getFieldable("i_field").getBoost(), equalTo(4.0f));
assertThat(doc.masterDoc().getFieldable("sh_field").getBoost(), equalTo(5.0f));
assertThat(doc.masterDoc().getFieldable("b_field").getBoost(), equalTo(6.0f));
assertThat(doc.masterDoc().getFieldable("d_field").getBoost(), equalTo(7.0f));
assertThat(doc.masterDoc().getFieldable("f_field").getBoost(), equalTo(8.0f));
assertThat(doc.masterDoc().getFieldable("date_field").getBoost(), equalTo(9.0f));
}
}