|
@@ -20,9 +20,11 @@
|
|
|
package org.elasticsearch.search;
|
|
|
|
|
|
import org.apache.lucene.util.BytesRef;
|
|
|
+import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
|
|
import org.elasticsearch.common.io.stream.Writeable;
|
|
|
+import org.elasticsearch.common.lucene.Lucene;
|
|
|
import org.elasticsearch.common.xcontent.ToXContentFragment;
|
|
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
|
|
import org.elasticsearch.common.xcontent.XContentParser;
|
|
@@ -35,101 +37,56 @@ import java.util.Objects;
|
|
|
|
|
|
public class SearchSortValues implements ToXContentFragment, Writeable {
|
|
|
|
|
|
- static final SearchSortValues EMPTY = new SearchSortValues(new Object[0]);
|
|
|
- private final Object[] sortValues;
|
|
|
+ private static final Object[] EMPTY_ARRAY = new Object[0];
|
|
|
+ static final SearchSortValues EMPTY = new SearchSortValues(EMPTY_ARRAY);
|
|
|
+
|
|
|
+ private final Object[] formattedSortValues;
|
|
|
+ private final Object[] rawSortValues;
|
|
|
|
|
|
SearchSortValues(Object[] sortValues) {
|
|
|
- this.sortValues = Objects.requireNonNull(sortValues, "sort values must not be empty");
|
|
|
+ this.formattedSortValues = Objects.requireNonNull(sortValues, "sort values must not be empty");
|
|
|
+ this.rawSortValues = EMPTY_ARRAY;
|
|
|
}
|
|
|
|
|
|
- public SearchSortValues(Object[] sortValues, DocValueFormat[] sortValueFormats) {
|
|
|
- Objects.requireNonNull(sortValues);
|
|
|
+ public SearchSortValues(Object[] rawSortValues, DocValueFormat[] sortValueFormats) {
|
|
|
+ Objects.requireNonNull(rawSortValues);
|
|
|
Objects.requireNonNull(sortValueFormats);
|
|
|
- this.sortValues = Arrays.copyOf(sortValues, sortValues.length);
|
|
|
- for (int i = 0; i < sortValues.length; ++i) {
|
|
|
- if (this.sortValues[i] instanceof BytesRef) {
|
|
|
- this.sortValues[i] = sortValueFormats[i].format((BytesRef) sortValues[i]);
|
|
|
+ if (rawSortValues.length != sortValueFormats.length) {
|
|
|
+ throw new IllegalArgumentException("formattedSortValues and sortValueFormats must hold the same number of items");
|
|
|
+ }
|
|
|
+ this.rawSortValues = rawSortValues;
|
|
|
+ this.formattedSortValues = Arrays.copyOf(rawSortValues, rawSortValues.length);
|
|
|
+ for (int i = 0; i < rawSortValues.length; ++i) {
|
|
|
+ //we currently format only BytesRef but we may want to change that in the future
|
|
|
+ Object sortValue = rawSortValues[i];
|
|
|
+ if (sortValue instanceof BytesRef) {
|
|
|
+ this.formattedSortValues[i] = sortValueFormats[i].format((BytesRef) sortValue);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public SearchSortValues(StreamInput in) throws IOException {
|
|
|
- int size = in.readVInt();
|
|
|
- if (size > 0) {
|
|
|
- sortValues = new Object[size];
|
|
|
- for (int i = 0; i < sortValues.length; i++) {
|
|
|
- byte type = in.readByte();
|
|
|
- if (type == 0) {
|
|
|
- sortValues[i] = null;
|
|
|
- } else if (type == 1) {
|
|
|
- sortValues[i] = in.readString();
|
|
|
- } else if (type == 2) {
|
|
|
- sortValues[i] = in.readInt();
|
|
|
- } else if (type == 3) {
|
|
|
- sortValues[i] = in.readLong();
|
|
|
- } else if (type == 4) {
|
|
|
- sortValues[i] = in.readFloat();
|
|
|
- } else if (type == 5) {
|
|
|
- sortValues[i] = in.readDouble();
|
|
|
- } else if (type == 6) {
|
|
|
- sortValues[i] = in.readByte();
|
|
|
- } else if (type == 7) {
|
|
|
- sortValues[i] = in.readShort();
|
|
|
- } else if (type == 8) {
|
|
|
- sortValues[i] = in.readBoolean();
|
|
|
- } else {
|
|
|
- throw new IOException("Can't match type [" + type + "]");
|
|
|
- }
|
|
|
- }
|
|
|
+ SearchSortValues(StreamInput in) throws IOException {
|
|
|
+ this.formattedSortValues = in.readArray(Lucene::readSortValue, Object[]::new);
|
|
|
+ if (in.getVersion().onOrAfter(Version.V_7_0_0)) {
|
|
|
+ this.rawSortValues = in.readArray(Lucene::readSortValue, Object[]::new);
|
|
|
} else {
|
|
|
- sortValues = new Object[0];
|
|
|
+ this.rawSortValues = EMPTY_ARRAY;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void writeTo(StreamOutput out) throws IOException {
|
|
|
- out.writeVInt(sortValues.length);
|
|
|
- for (Object sortValue : sortValues) {
|
|
|
- if (sortValue == null) {
|
|
|
- out.writeByte((byte) 0);
|
|
|
- } else {
|
|
|
- Class type = sortValue.getClass();
|
|
|
- if (type == String.class) {
|
|
|
- out.writeByte((byte) 1);
|
|
|
- out.writeString((String) sortValue);
|
|
|
- } else if (type == Integer.class) {
|
|
|
- out.writeByte((byte) 2);
|
|
|
- out.writeInt((Integer) sortValue);
|
|
|
- } else if (type == Long.class) {
|
|
|
- out.writeByte((byte) 3);
|
|
|
- out.writeLong((Long) sortValue);
|
|
|
- } else if (type == Float.class) {
|
|
|
- out.writeByte((byte) 4);
|
|
|
- out.writeFloat((Float) sortValue);
|
|
|
- } else if (type == Double.class) {
|
|
|
- out.writeByte((byte) 5);
|
|
|
- out.writeDouble((Double) sortValue);
|
|
|
- } else if (type == Byte.class) {
|
|
|
- out.writeByte((byte) 6);
|
|
|
- out.writeByte((Byte) sortValue);
|
|
|
- } else if (type == Short.class) {
|
|
|
- out.writeByte((byte) 7);
|
|
|
- out.writeShort((Short) sortValue);
|
|
|
- } else if (type == Boolean.class) {
|
|
|
- out.writeByte((byte) 8);
|
|
|
- out.writeBoolean((Boolean) sortValue);
|
|
|
- } else {
|
|
|
- throw new IOException("Can't handle sort field value of type [" + type + "]");
|
|
|
- }
|
|
|
- }
|
|
|
+ out.writeArray(Lucene::writeSortValue, this.formattedSortValues);
|
|
|
+ if (out.getVersion().onOrAfter(Version.V_7_0_0)) {
|
|
|
+ out.writeArray(Lucene::writeSortValue, this.rawSortValues);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
|
|
- if (sortValues.length > 0) {
|
|
|
+ if (formattedSortValues.length > 0) {
|
|
|
builder.startArray(Fields.SORT);
|
|
|
- for (Object sortValue : sortValues) {
|
|
|
+ for (Object sortValue : formattedSortValues) {
|
|
|
builder.value(sortValue);
|
|
|
}
|
|
|
builder.endArray();
|
|
@@ -142,24 +99,37 @@ public class SearchSortValues implements ToXContentFragment, Writeable {
|
|
|
return new SearchSortValues(parser.list().toArray());
|
|
|
}
|
|
|
|
|
|
- public Object[] sortValues() {
|
|
|
- return sortValues;
|
|
|
+ /**
|
|
|
+ * Returns the formatted version of the values that sorting was performed against
|
|
|
+ */
|
|
|
+ public Object[] getFormattedSortValues() {
|
|
|
+ return formattedSortValues;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Returns the raw version of the values that sorting was performed against
|
|
|
+ */
|
|
|
+ public Object[] getRawSortValues() {
|
|
|
+ return rawSortValues;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public boolean equals(Object obj) {
|
|
|
- if (this == obj) {
|
|
|
+ public boolean equals(Object o) {
|
|
|
+ if (this == o) {
|
|
|
return true;
|
|
|
}
|
|
|
- if (obj == null || getClass() != obj.getClass()) {
|
|
|
+ if (o == null || getClass() != o.getClass()) {
|
|
|
return false;
|
|
|
}
|
|
|
- SearchSortValues other = (SearchSortValues) obj;
|
|
|
- return Arrays.equals(sortValues, other.sortValues);
|
|
|
+ SearchSortValues that = (SearchSortValues) o;
|
|
|
+ return Arrays.equals(formattedSortValues, that.formattedSortValues) &&
|
|
|
+ Arrays.equals(rawSortValues, that.rawSortValues);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public int hashCode() {
|
|
|
- return Arrays.hashCode(sortValues);
|
|
|
+ int result = Arrays.hashCode(formattedSortValues);
|
|
|
+ result = 31 * result + Arrays.hashCode(rawSortValues);
|
|
|
+ return result;
|
|
|
}
|
|
|
}
|