Skip to content

Commit 621d222

Browse files
committed
Mapping: Support for short type, closes #84.
1 parent 0a2de7c commit 621d222

File tree

5 files changed

+227
-0
lines changed

5 files changed

+227
-0
lines changed

modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDocumentMapperParser.java

+16
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ private void parseProperties(JsonObjectMapper.Builder objBuilder, ObjectNode pro
294294
objBuilder.add(parseString(propName, (ObjectNode) propNode));
295295
} else if (type.equals(JsonDateFieldMapper.JSON_TYPE)) {
296296
objBuilder.add(parseDate(propName, (ObjectNode) propNode));
297+
} else if (type.equals(JsonShortFieldMapper.JSON_TYPE)) {
298+
objBuilder.add(parseShort(propName, (ObjectNode) propNode));
297299
} else if (type.equals(JsonIntegerFieldMapper.JSON_TYPE)) {
298300
objBuilder.add(parseInteger(propName, (ObjectNode) propNode));
299301
} else if (type.equals(JsonLongFieldMapper.JSON_TYPE)) {
@@ -376,6 +378,20 @@ private JsonDateFieldMapper.Builder parseDate(String name, ObjectNode dateNode)
376378
return builder;
377379
}
378380

381+
private JsonShortFieldMapper.Builder parseShort(String name, ObjectNode integerNode) {
382+
JsonShortFieldMapper.Builder builder = shortField(name);
383+
parseNumberField(builder, name, integerNode);
384+
for (Iterator<Map.Entry<String, JsonNode>> propsIt = integerNode.getFields(); propsIt.hasNext();) {
385+
Map.Entry<String, JsonNode> entry = propsIt.next();
386+
String propName = entry.getKey();
387+
JsonNode propNode = entry.getValue();
388+
if (propName.equals("nullValue")) {
389+
builder.nullValue(nodeShortValue(propNode));
390+
}
391+
}
392+
return builder;
393+
}
394+
379395

380396
private JsonIntegerFieldMapper.Builder parseInteger(String name, ObjectNode integerNode) {
381397
JsonIntegerFieldMapper.Builder builder = integerField(name);

modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonMapperBuilders.java

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ public static JsonDateFieldMapper.Builder dateField(String name) {
8080
return new JsonDateFieldMapper.Builder(name);
8181
}
8282

83+
public static JsonShortFieldMapper.Builder shortField(String name) {
84+
return new JsonShortFieldMapper.Builder(name);
85+
}
86+
8387
public static JsonIntegerFieldMapper.Builder integerField(String name) {
8488
return new JsonIntegerFieldMapper.Builder(name);
8589
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Licensed to Elastic Search and Shay Banon under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. Elastic Search licenses this
6+
* file to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.index.mapper.json;
21+
22+
import org.apache.lucene.document.Field;
23+
import org.apache.lucene.document.Fieldable;
24+
import org.apache.lucene.search.*;
25+
import org.apache.lucene.util.NumericUtils;
26+
import org.codehaus.jackson.JsonToken;
27+
import org.elasticsearch.index.analysis.NamedAnalyzer;
28+
import org.elasticsearch.index.analysis.NumericIntegerAnalyzer;
29+
import org.elasticsearch.util.Numbers;
30+
import org.elasticsearch.util.json.JsonBuilder;
31+
32+
import java.io.IOException;
33+
34+
/**
35+
* @author kimchy (shay.banon)
36+
*/
37+
public class JsonShortFieldMapper extends JsonNumberFieldMapper<Short> {
38+
39+
public static final String JSON_TYPE = "short";
40+
41+
public static class Defaults extends JsonNumberFieldMapper.Defaults {
42+
public static final Short NULL_VALUE = null;
43+
}
44+
45+
public static class Builder extends JsonNumberFieldMapper.Builder<Builder, JsonShortFieldMapper> {
46+
47+
protected Short nullValue = Defaults.NULL_VALUE;
48+
49+
public Builder(String name) {
50+
super(name);
51+
builder = this;
52+
}
53+
54+
public Builder nullValue(short nullValue) {
55+
this.nullValue = nullValue;
56+
return this;
57+
}
58+
59+
@Override public JsonShortFieldMapper build(BuilderContext context) {
60+
JsonShortFieldMapper fieldMapper = new JsonShortFieldMapper(buildNames(context),
61+
precisionStep, index, store, boost, omitNorms, omitTermFreqAndPositions, nullValue);
62+
fieldMapper.includeInAll(includeInAll);
63+
return fieldMapper;
64+
}
65+
}
66+
67+
private final Short nullValue;
68+
69+
private final String nullValueAsString;
70+
71+
protected JsonShortFieldMapper(Names names, int precisionStep, Field.Index index, Field.Store store,
72+
float boost, boolean omitNorms, boolean omitTermFreqAndPositions,
73+
Short nullValue) {
74+
super(names, precisionStep, index, store, boost, omitNorms, omitTermFreqAndPositions,
75+
new NamedAnalyzer("_short/" + precisionStep, new NumericIntegerAnalyzer(precisionStep)),
76+
new NamedAnalyzer("_short/max", new NumericIntegerAnalyzer(Integer.MAX_VALUE)));
77+
this.nullValue = nullValue;
78+
this.nullValueAsString = nullValue == null ? null : nullValue.toString();
79+
}
80+
81+
@Override protected int maxPrecisionStep() {
82+
return 32;
83+
}
84+
85+
@Override public Short value(Fieldable field) {
86+
byte[] value = field.getBinaryValue();
87+
if (value == null) {
88+
return Short.MIN_VALUE;
89+
}
90+
return Numbers.bytesToShort(value);
91+
}
92+
93+
@Override public String indexedValue(String value) {
94+
return indexedValue(Short.parseShort(value));
95+
}
96+
97+
@Override public String indexedValue(Short value) {
98+
return NumericUtils.intToPrefixCoded(value);
99+
}
100+
101+
@Override public Object valueFromTerm(String term) {
102+
final int shift = term.charAt(0) - NumericUtils.SHIFT_START_INT;
103+
if (shift > 0 && shift <= 31) {
104+
return null;
105+
}
106+
return NumericUtils.prefixCodedToInt(term);
107+
}
108+
109+
@Override public Object valueFromString(String text) {
110+
return Short.parseShort(text);
111+
}
112+
113+
@Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
114+
return NumericRangeQuery.newIntRange(names.indexName(), precisionStep,
115+
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
116+
upperTerm == null ? null : Integer.parseInt(upperTerm),
117+
includeLower, includeUpper);
118+
}
119+
120+
@Override public Filter rangeFilter(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) {
121+
return NumericRangeFilter.newIntRange(names.indexName(), precisionStep,
122+
lowerTerm == null ? null : Integer.parseInt(lowerTerm),
123+
upperTerm == null ? null : Integer.parseInt(upperTerm),
124+
includeLower, includeUpper);
125+
}
126+
127+
@Override protected Field parseCreateField(JsonParseContext jsonContext) throws IOException {
128+
int value;
129+
if (jsonContext.jp().getCurrentToken() == JsonToken.VALUE_NULL) {
130+
if (nullValue == null) {
131+
return null;
132+
}
133+
value = nullValue;
134+
if (includeInAll == null || includeInAll) {
135+
jsonContext.allEntries().addText(names.fullName(), nullValueAsString, boost);
136+
}
137+
} else {
138+
if (jsonContext.jp().getCurrentToken() == JsonToken.VALUE_STRING) {
139+
value = Integer.parseInt(jsonContext.jp().getText());
140+
} else {
141+
value = jsonContext.jp().getIntValue();
142+
}
143+
if (includeInAll == null || includeInAll) {
144+
jsonContext.allEntries().addText(names.fullName(), jsonContext.jp().getText(), boost);
145+
}
146+
}
147+
Field field = null;
148+
if (stored()) {
149+
field = new Field(names.indexName(), Numbers.shortToBytes(value), store);
150+
if (indexed()) {
151+
field.setTokenStream(popCachedStream(precisionStep).setIntValue(value));
152+
}
153+
} else if (indexed()) {
154+
field = new Field(names.indexName(), popCachedStream(precisionStep).setIntValue(value));
155+
}
156+
return field;
157+
}
158+
159+
@Override public int sortType() {
160+
return SortField.SHORT;
161+
}
162+
163+
@Override protected String jsonType() {
164+
return JSON_TYPE;
165+
}
166+
167+
@Override protected void doJsonBody(JsonBuilder builder) throws IOException {
168+
super.doJsonBody(builder);
169+
if (nullValue != null) {
170+
builder.field("nullValue", nullValue);
171+
}
172+
if (includeInAll != null) {
173+
builder.field("includeInAll", includeInAll);
174+
}
175+
}
176+
}

modules/elasticsearch/src/main/java/org/elasticsearch/util/Numbers.java

+23
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ private Numbers() {
3030

3131
}
3232

33+
/**
34+
* Converts a byte array to an short.
35+
*
36+
* @param arr The byte array to convert to an short
37+
* @return The int converted
38+
*/
39+
public static short bytesToShort(byte[] arr) {
40+
return (short) (((arr[2] & 0xff) << 8) | (arr[3] & 0xff));
41+
}
42+
3343
/**
3444
* Converts a byte array to an int.
3545
*
@@ -87,6 +97,19 @@ public static byte[] intToBytes(int val) {
8797
return arr;
8898
}
8999

100+
/**
101+
* Converts an int to a byte array.
102+
*
103+
* @param val The int to convert to a byte array
104+
* @return The byte array converted
105+
*/
106+
public static byte[] shortToBytes(int val) {
107+
byte[] arr = new byte[2];
108+
arr[2] = (byte) (val >>> 8);
109+
arr[3] = (byte) (val);
110+
return arr;
111+
}
112+
90113
/**
91114
* Converts a long to a byte array.
92115
*

modules/elasticsearch/src/main/java/org/elasticsearch/util/json/JacksonNodes.java

+8
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ public static int nodeIntegerValue(JsonNode node) {
5050
return Integer.parseInt(value);
5151
}
5252

53+
public static short nodeShortValue(JsonNode node) {
54+
if (node.isNumber()) {
55+
return node.getNumberValue().shortValue();
56+
}
57+
String value = node.getTextValue();
58+
return Short.parseShort(value);
59+
}
60+
5361
public static long nodeLongValue(JsonNode node) {
5462
if (node.isNumber()) {
5563
return node.getNumberValue().longValue();

0 commit comments

Comments
 (0)