Mapping: Support for short type, closes #84.

This commit is contained in:
kimchy 2010-03-23 14:20:56 +02:00
parent 0a2de7ce5d
commit 621d222c94
5 changed files with 227 additions and 0 deletions

View File

@ -294,6 +294,8 @@ public class JsonDocumentMapperParser implements DocumentMapperParser {
objBuilder.add(parseString(propName, (ObjectNode) propNode));
} else if (type.equals(JsonDateFieldMapper.JSON_TYPE)) {
objBuilder.add(parseDate(propName, (ObjectNode) propNode));
} else if (type.equals(JsonShortFieldMapper.JSON_TYPE)) {
objBuilder.add(parseShort(propName, (ObjectNode) propNode));
} else if (type.equals(JsonIntegerFieldMapper.JSON_TYPE)) {
objBuilder.add(parseInteger(propName, (ObjectNode) propNode));
} else if (type.equals(JsonLongFieldMapper.JSON_TYPE)) {
@ -376,6 +378,20 @@ public class JsonDocumentMapperParser implements DocumentMapperParser {
return builder;
}
private JsonShortFieldMapper.Builder parseShort(String name, ObjectNode integerNode) {
JsonShortFieldMapper.Builder builder = shortField(name);
parseNumberField(builder, name, integerNode);
for (Iterator<Map.Entry<String, JsonNode>> propsIt = integerNode.getFields(); propsIt.hasNext();) {
Map.Entry<String, JsonNode> entry = propsIt.next();
String propName = entry.getKey();
JsonNode propNode = entry.getValue();
if (propName.equals("nullValue")) {
builder.nullValue(nodeShortValue(propNode));
}
}
return builder;
}
private JsonIntegerFieldMapper.Builder parseInteger(String name, ObjectNode integerNode) {
JsonIntegerFieldMapper.Builder builder = integerField(name);

View File

@ -80,6 +80,10 @@ public final class JsonMapperBuilders {
return new JsonDateFieldMapper.Builder(name);
}
public static JsonShortFieldMapper.Builder shortField(String name) {
return new JsonShortFieldMapper.Builder(name);
}
public static JsonIntegerFieldMapper.Builder integerField(String name) {
return new JsonIntegerFieldMapper.Builder(name);
}

View File

@ -0,0 +1,176 @@
/*
* 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.json;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.search.*;
import org.apache.lucene.util.NumericUtils;
import org.codehaus.jackson.JsonToken;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.NumericIntegerAnalyzer;
import org.elasticsearch.util.Numbers;
import org.elasticsearch.util.json.JsonBuilder;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class JsonShortFieldMapper extends JsonNumberFieldMapper<Short> {
public static final String JSON_TYPE = "short";
public static class Defaults extends JsonNumberFieldMapper.Defaults {
public static final Short NULL_VALUE = null;
}
public static class Builder extends JsonNumberFieldMapper.Builder<Builder, JsonShortFieldMapper> {
protected Short nullValue = Defaults.NULL_VALUE;
public Builder(String name) {
super(name);
builder = this;
}
public Builder nullValue(short nullValue) {
this.nullValue = nullValue;
return this;
}
@Override public JsonShortFieldMapper build(BuilderContext context) {
JsonShortFieldMapper fieldMapper = new JsonShortFieldMapper(buildNames(context),
precisionStep, index, store, boost, omitNorms, omitTermFreqAndPositions, nullValue);
fieldMapper.includeInAll(includeInAll);
return fieldMapper;
}
}
private final Short nullValue;
private final String nullValueAsString;
protected JsonShortFieldMapper(Names names, int precisionStep, Field.Index index, Field.Store store,
float boost, boolean omitNorms, boolean omitTermFreqAndPositions,
Short nullValue) {
super(names, precisionStep, index, store, boost, omitNorms, omitTermFreqAndPositions,
new NamedAnalyzer("_short/" + precisionStep, new NumericIntegerAnalyzer(precisionStep)),
new NamedAnalyzer("_short/max", new NumericIntegerAnalyzer(Integer.MAX_VALUE)));
this.nullValue = nullValue;
this.nullValueAsString = nullValue == null ? null : nullValue.toString();
}
@Override protected int maxPrecisionStep() {
return 32;
}
@Override public Short value(Fieldable field) {
byte[] value = field.getBinaryValue();
if (value == null) {
return Short.MIN_VALUE;
}
return Numbers.bytesToShort(value);
}
@Override public String indexedValue(String value) {
return indexedValue(Short.parseShort(value));
}
@Override public String indexedValue(Short value) {
return NumericUtils.intToPrefixCoded(value);
}
@Override public Object valueFromTerm(String term) {
final int shift = term.charAt(0) - NumericUtils.SHIFT_START_INT;
if (shift > 0 && shift <= 31) {
return null;
}
return NumericUtils.prefixCodedToInt(term);
}
@Override public Object valueFromString(String text) {
return Short.parseShort(text);
}
@Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
upperTerm == null ? null : Integer.parseInt(upperTerm),
includeLower, includeUpper);
}
@Override public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
upperTerm == null ? null : Integer.parseInt(upperTerm),
includeLower, includeUpper);
}
@Override protected Field parseCreateField(JsonParseContext jsonContext) throws IOException {
int value;
if (jsonContext.jp().getCurrentToken() == JsonToken.VALUE_NULL) {
if (nullValue == null) {
return null;
}
value = nullValue;
if (includeInAll == null || includeInAll) {
jsonContext.allEntries().addText(names.fullName(), nullValueAsString, boost);
}
} else {
if (jsonContext.jp().getCurrentToken() == JsonToken.VALUE_STRING) {
value = Integer.parseInt(jsonContext.jp().getText());
} else {
value = jsonContext.jp().getIntValue();
}
if (includeInAll == null || includeInAll) {
jsonContext.allEntries().addText(names.fullName(), jsonContext.jp().getText(), boost);
}
}
Field field = null;
if (stored()) {
field = new Field(names.indexName(), Numbers.shortToBytes(value), store);
if (indexed()) {
field.setTokenStream(popCachedStream(precisionStep).setIntValue(value));
}
} else if (indexed()) {
field = new Field(names.indexName(), popCachedStream(precisionStep).setIntValue(value));
}
return field;
}
@Override public int sortType() {
return SortField.SHORT;
}
@Override protected String jsonType() {
return JSON_TYPE;
}
@Override protected void doJsonBody(JsonBuilder builder) throws IOException {
super.doJsonBody(builder);
if (nullValue != null) {
builder.field("nullValue", nullValue);
}
if (includeInAll != null) {
builder.field("includeInAll", includeInAll);
}
}
}

View File

@ -30,6 +30,16 @@ public final class Numbers {
}
/**
* Converts a byte array to an short.
*
* @param arr The byte array to convert to an short
* @return The int converted
*/
public static short bytesToShort(byte[] arr) {
return (short) (((arr[2] & 0xff) << 8) | (arr[3] & 0xff));
}
/**
* Converts a byte array to an int.
*
@ -87,6 +97,19 @@ public final class Numbers {
return arr;
}
/**
* Converts an int to a byte array.
*
* @param val The int to convert to a byte array
* @return The byte array converted
*/
public static byte[] shortToBytes(int val) {
byte[] arr = new byte[2];
arr[2] = (byte) (val >>> 8);
arr[3] = (byte) (val);
return arr;
}
/**
* Converts a long to a byte array.
*

View File

@ -50,6 +50,14 @@ public class JacksonNodes {
return Integer.parseInt(value);
}
public static short nodeShortValue(JsonNode node) {
if (node.isNumber()) {
return node.getNumberValue().shortValue();
}
String value = node.getTextValue();
return Short.parseShort(value);
}
public static long nodeLongValue(JsonNode node) {
if (node.isNumber()) {
return node.getNumberValue().longValue();