diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TermsRequest.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TermsRequest.java index 4b3c2cae1a5..7e488a8ec2a 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TermsRequest.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TermsRequest.java @@ -20,6 +20,7 @@ package org.elasticsearch.action.terms; import org.elasticsearch.ElasticSearchIllegalArgumentException; +import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.support.broadcast.BroadcastOperationRequest; import org.elasticsearch.index.mapper.AllFieldMapper; import org.elasticsearch.util.io.stream.StreamInput; @@ -141,6 +142,14 @@ public class TermsRequest extends BroadcastOperationRequest { super(indices, null); } + @Override public ActionRequestValidationException validate() { + ActionRequestValidationException validationException = super.validate(); + if (fields == null || fields.length == 0) { + fields = DEFAULT_FIELDS; + } + return validationException; + } + /** * The fields within each document which terms will be iterated over and returned with the * document frequencies. diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TransportTermsAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TransportTermsAction.java index d192b1a96ab..3427a93d229 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TransportTermsAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/terms/TransportTermsAction.java @@ -196,6 +196,18 @@ public class TransportTermsAction extends TransportBroadcastOperationAction<Term if (term == null || indexFieldName != term.field()) { // StirngHelper.intern break; } + // convert to actual term text + if (fieldMapper != null && fieldMapper.requiresStringToStringConversion()) { + // valueAsString returns null indicating that this is not interesting + term = term.createTerm(fieldMapper.valueAsString(term.text())); + // if we need to break on this term enumeration, bail + if (fieldMapper.shouldBreakTermEnumeration(term.text())) { + break; + } + if (term.text() == null) { + continue; + } + } // does it match on the prefix? if (request.prefix() != null && !term.text().startsWith(request.prefix())) { break; @@ -240,6 +252,18 @@ public class TransportTermsAction extends TransportBroadcastOperationAction<Term if (term == null || indexFieldName != term.field()) { // StirngHelper.intern break; } + // convert to actual term text + if (fieldMapper != null && fieldMapper.requiresStringToStringConversion()) { + // valueAsString returns null indicating that this is not interesting + term = term.createTerm(fieldMapper.valueAsString(term.text())); + // if we need to break on this term enumeration, bail + if (fieldMapper.shouldBreakTermEnumeration(term.text())) { + break; + } + if (term.text() == null) { + continue; + } + } // does it match on the prefix? if (request.prefix() != null && !term.text().startsWith(request.prefix())) { break; diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/node/Node.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/node/Node.java index dbb0bb9c558..678ac34445c 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/node/Node.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/node/Node.java @@ -20,6 +20,7 @@ package org.elasticsearch.cluster.node; import com.google.common.collect.ImmutableList; +import org.apache.lucene.util.StringHelper; import org.elasticsearch.util.io.stream.StreamInput; import org.elasticsearch.util.io.stream.StreamOutput; import org.elasticsearch.util.io.stream.Streamable; @@ -36,7 +37,7 @@ public class Node implements Streamable, Serializable { public static final ImmutableList<Node> EMPTY_LIST = ImmutableList.of(); - private String nodeName = ""; + private String nodeName = StringHelper.intern(""); private String nodeId; @@ -52,12 +53,13 @@ public class Node implements Streamable, Serializable { } public Node(String nodeName, boolean dataNode, String nodeId, TransportAddress address) { - this.nodeName = nodeName; - this.dataNode = dataNode; - if (this.nodeName == null) { - this.nodeName = ""; + if (nodeName == null) { + this.nodeName = StringHelper.intern(""); + } else { + this.nodeName = StringHelper.intern(nodeName); } - this.nodeId = nodeId; + this.dataNode = dataNode; + this.nodeId = StringHelper.intern(nodeId); this.address = address; } @@ -96,9 +98,9 @@ public class Node implements Streamable, Serializable { } @Override public void readFrom(StreamInput in) throws IOException { - nodeName = in.readUTF(); + nodeName = StringHelper.intern(in.readUTF()); dataNode = in.readBoolean(); - nodeId = in.readUTF(); + nodeId = StringHelper.intern(in.readUTF()); address = TransportAddressSerializers.addressFromStream(in); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/Index.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/Index.java index ee3223c9a01..ffa4cc18d66 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/Index.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/Index.java @@ -19,6 +19,7 @@ package org.elasticsearch.index; +import org.apache.lucene.util.StringHelper; import org.elasticsearch.util.concurrent.Immutable; import org.elasticsearch.util.io.stream.StreamInput; import org.elasticsearch.util.io.stream.StreamOutput; @@ -40,7 +41,7 @@ public class Index implements Serializable, Streamable { } public Index(String name) { - this.name = name; + this.name = StringHelper.intern(name); } public String name() { @@ -73,7 +74,7 @@ public class Index implements Serializable, Streamable { } @Override public void readFrom(StreamInput in) throws IOException { - name = in.readUTF(); + name = StringHelper.intern(in.readUTF()); } @Override public void writeTo(StreamOutput out) throws IOException { diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java index 03b357afae9..de5ffffc1c0 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/FieldMapper.java @@ -128,6 +128,25 @@ public interface FieldMapper<T> { */ String valueAsString(Fieldable field); + /** + * Returns <tt>true</tt> if {@link #valueAsString(String)} is required to convert + * from text value to text value. + */ + boolean requiresStringToStringConversion(); + + /** + * Converts from the internal/indexed (term) text to the actual string representation. + * Can return <tt>null</tt> indicating that this is "uninteresting" value (for example, with + * numbers). Useful for example when enumerating terms. See {@link #shouldBreakTermEnumeration(String)}. + */ + String valueAsString(String text); + + /** + * Return <tt>true</tt> if this term value indicates breaking out of term enumeration on this + * field. The term text passed is the one returned from {@link #valueAsString(String)}. + */ + boolean shouldBreakTermEnumeration(String text); + /** * Returns the indexed value. */ diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonBoostFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonBoostFieldMapper.java index ff4061f6909..89c113342a7 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonBoostFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonBoostFieldMapper.java @@ -110,6 +110,14 @@ public class JsonBoostFieldMapper extends JsonNumberFieldMapper<Float> implement return NumericUtils.floatToPrefixCoded(value); } + @Override public String valueAsString(String text) { + final int shift = text.charAt(0) - NumericUtils.SHIFT_START_INT; + if (shift > 0 && shift <= 31) { + return null; + } + return Float.toString(NumericUtils.prefixCodedToFloat(text)); + } + @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep, lowerTerm == null ? null : Float.parseFloat(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDateFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDateFieldMapper.java index 0d2490285b6..e4186482f3b 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDateFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDateFieldMapper.java @@ -115,6 +115,14 @@ public class JsonDateFieldMapper extends JsonNumberFieldMapper<Long> { return NumericUtils.longToPrefixCoded(value); } + @Override public String valueAsString(String text) { + final int shift = text.charAt(0) - NumericUtils.SHIFT_START_LONG; + if (shift > 0 && shift <= 63) { + return null; + } + return dateTimeFormatter.printer().print(NumericUtils.prefixCodedToLong(text)); + } + @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return NumericRangeQuery.newLongRange(names.indexName(), precisionStep, lowerTerm == null ? null : dateTimeFormatter.parser().parseMillis(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDoubleFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDoubleFieldMapper.java index 554fe669ea4..544f13e06da 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDoubleFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonDoubleFieldMapper.java @@ -99,6 +99,14 @@ public class JsonDoubleFieldMapper extends JsonNumberFieldMapper<Double> { return NumericUtils.doubleToPrefixCoded(value); } + @Override public String valueAsString(String text) { + final int shift = text.charAt(0) - NumericUtils.SHIFT_START_LONG; + if (shift > 0 && shift <= 63) { + return null; + } + return Double.toString(NumericUtils.prefixCodedToDouble(text)); + } + @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return NumericRangeQuery.newDoubleRange(names.indexName(), precisionStep, lowerTerm == null ? null : Double.parseDouble(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFieldMapper.java index f85285db1bb..ab018930f8c 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFieldMapper.java @@ -292,6 +292,27 @@ public abstract class JsonFieldMapper<T> implements FieldMapper<T>, JsonMapper { return valueAsString(field); } + /** + * Default base does not require stringToString conversion. + */ + @Override public boolean requiresStringToStringConversion() { + return false; + } + + /** + * Simply returns the same string. + */ + @Override public String valueAsString(String text) { + return text; + } + + /** + * Never break on this term enumeration value. + */ + @Override public boolean shouldBreakTermEnumeration(String text) { + return false; + } + @Override public String indexedValue(String value) { return value; } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFloatFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFloatFieldMapper.java index 865ba811295..1bee19bab74 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFloatFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonFloatFieldMapper.java @@ -99,6 +99,14 @@ public class JsonFloatFieldMapper extends JsonNumberFieldMapper<Float> { return NumericUtils.floatToPrefixCoded(value); } + @Override public String valueAsString(String text) { + final int shift = text.charAt(0) - NumericUtils.SHIFT_START_INT; + if (shift > 0 && shift <= 31) { + return null; + } + return Float.toString(NumericUtils.prefixCodedToFloat(text)); + } + @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return NumericRangeQuery.newFloatRange(names.indexName(), precisionStep, lowerTerm == null ? null : Float.parseFloat(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonIntegerFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonIntegerFieldMapper.java index e06407d5546..12820c5454c 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonIntegerFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonIntegerFieldMapper.java @@ -98,6 +98,10 @@ public class JsonIntegerFieldMapper extends JsonNumberFieldMapper<Integer> { return NumericUtils.intToPrefixCoded(value); } + @Override public String valueAsString(String text) { + return Integer.toString(NumericUtils.prefixCodedToInt(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), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonLongFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonLongFieldMapper.java index dc3076873e0..37a826418fb 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonLongFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonLongFieldMapper.java @@ -98,6 +98,14 @@ public class JsonLongFieldMapper extends JsonNumberFieldMapper<Long> { return NumericUtils.longToPrefixCoded(value); } + @Override public String valueAsString(String text) { + final int shift = text.charAt(0) - NumericUtils.SHIFT_START_LONG; + if (shift > 0 && shift <= 63) { + return null; + } + return Long.toString(NumericUtils.prefixCodedToLong(text)); + } + @Override public Query rangeQuery(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper) { return NumericRangeQuery.newLongRange(names.indexName(), precisionStep, lowerTerm == null ? null : Long.parseLong(lowerTerm), diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonNumberFieldMapper.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonNumberFieldMapper.java index c5fd87e1c6d..a2940067b5b 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonNumberFieldMapper.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/mapper/json/JsonNumberFieldMapper.java @@ -129,6 +129,22 @@ public abstract class JsonNumberFieldMapper<T extends Number> extends JsonFieldM return value(field).toString(); } + /** + * Numbers require string conversion. + */ + @Override public boolean requiresStringToStringConversion() { + return true; + } + + @Override public abstract String valueAsString(String text); + + /** + * Breaks on this text if its <tt>null</tt>. + */ + @Override public boolean shouldBreakTermEnumeration(String text) { + return text == null; + } + @Override protected void doJsonBody(JsonBuilder builder) throws IOException { super.doJsonBody(builder); builder.field("precisionStep", precisionStep);