This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 186
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Only keep the first element of multivalue field response. (#1026)
* update * update * update * update * update * update * update * update * address comments, add doc * update
- Loading branch information
Showing
7 changed files
with
497 additions
and
184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
...main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/data/utils/Content.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file 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 com.amazon.opendistroforelasticsearch.sql.elasticsearch.data.utils; | ||
|
||
import java.util.Iterator; | ||
import java.util.Map; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
|
||
/** | ||
* Regardless the underling data format, the {@link Content} define the data in abstract manner. | ||
* which could be parsed by ElasticsearchExprValueFactory. | ||
* There are two major use cases: | ||
* 1. Represent the JSON data retrieve from Elasticsearch search response. | ||
* 2. Represent the Object data extract from the Elasticsearch aggregation response. | ||
*/ | ||
public interface Content { | ||
|
||
/** | ||
* Is null value. | ||
*/ | ||
boolean isNull(); | ||
|
||
/** | ||
* Is number value. | ||
*/ | ||
boolean isNumber(); | ||
|
||
/** | ||
* Is string value. | ||
*/ | ||
boolean isString(); | ||
|
||
/** | ||
* Get integer value. | ||
*/ | ||
Integer intValue(); | ||
|
||
/** | ||
* Get long value. | ||
*/ | ||
Long longValue(); | ||
|
||
/** | ||
* Get short value. | ||
*/ | ||
Short shortValue(); | ||
|
||
/** | ||
* Get byte value. | ||
*/ | ||
Byte byteValue(); | ||
|
||
/** | ||
* Get float value. | ||
*/ | ||
Float floatValue(); | ||
|
||
/** | ||
* Get double value. | ||
*/ | ||
Double doubleValue(); | ||
|
||
/** | ||
* Get string value. | ||
*/ | ||
String stringValue(); | ||
|
||
/** | ||
* Get boolean value. | ||
*/ | ||
Boolean booleanValue(); | ||
|
||
/** | ||
* Get map of {@link Content} value. | ||
*/ | ||
Iterator<Map.Entry<String, Content>> map(); | ||
|
||
/** | ||
* Get array of {@link Content} value. | ||
*/ | ||
Iterator<? extends Content> array(); | ||
|
||
/** | ||
* Get geo point value. | ||
*/ | ||
Pair<Double, Double> geoValue(); | ||
|
||
/** | ||
* Get {@link Object} value. | ||
*/ | ||
Object objectValue(); | ||
} |
123 changes: 123 additions & 0 deletions
123
...zon/opendistroforelasticsearch/sql/elasticsearch/data/utils/ElasticsearchJsonContent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file 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 com.amazon.opendistroforelasticsearch.sql.elasticsearch.data.utils; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.google.common.collect.Iterators; | ||
import java.util.Iterator; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
import lombok.RequiredArgsConstructor; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
|
||
/** | ||
* The Implementation of Content to represent {@link JsonNode}. | ||
*/ | ||
@RequiredArgsConstructor | ||
public class ElasticsearchJsonContent implements Content { | ||
|
||
private final JsonNode value; | ||
|
||
@Override | ||
public Integer intValue() { | ||
return value().intValue(); | ||
} | ||
|
||
@Override | ||
public Long longValue() { | ||
return value().longValue(); | ||
} | ||
|
||
@Override | ||
public Short shortValue() { | ||
return value().shortValue(); | ||
} | ||
|
||
@Override | ||
public Byte byteValue() { | ||
return (byte) value().shortValue(); | ||
} | ||
|
||
@Override | ||
public Float floatValue() { | ||
return value().floatValue(); | ||
} | ||
|
||
@Override | ||
public Double doubleValue() { | ||
return value().doubleValue(); | ||
} | ||
|
||
@Override | ||
public String stringValue() { | ||
return value().asText(); | ||
} | ||
|
||
@Override | ||
public Boolean booleanValue() { | ||
return value().booleanValue(); | ||
} | ||
|
||
@Override | ||
public Iterator<Map.Entry<String, Content>> map() { | ||
LinkedHashMap<String, Content> map = new LinkedHashMap<>(); | ||
final JsonNode mapValue = value(); | ||
mapValue | ||
.fieldNames() | ||
.forEachRemaining( | ||
field -> map.put(field, new ElasticsearchJsonContent(mapValue.get(field)))); | ||
return map.entrySet().iterator(); | ||
} | ||
|
||
@Override | ||
public Iterator<? extends Content> array() { | ||
return Iterators.transform(value.elements(), ElasticsearchJsonContent::new); | ||
} | ||
|
||
@Override | ||
public boolean isNull() { | ||
return value == null || value.isNull(); | ||
} | ||
|
||
@Override | ||
public boolean isNumber() { | ||
return value().isNumber(); | ||
} | ||
|
||
@Override | ||
public boolean isString() { | ||
return value().isTextual(); | ||
} | ||
|
||
@Override | ||
public Object objectValue() { | ||
return value(); | ||
} | ||
|
||
@Override | ||
public Pair<Double, Double> geoValue() { | ||
return Pair.of(value().get("lat").doubleValue(), value().get("lon").doubleValue()); | ||
} | ||
|
||
/** | ||
* Return the first element if is Elasticsearch Array. | ||
* https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html. | ||
*/ | ||
private JsonNode value() { | ||
return value.isArray() ? value.get(0) : value; | ||
} | ||
} |
125 changes: 125 additions & 0 deletions
125
...ava/com/amazon/opendistroforelasticsearch/sql/elasticsearch/data/utils/ObjectContent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file 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 com.amazon.opendistroforelasticsearch.sql.elasticsearch.data.utils; | ||
|
||
import java.util.AbstractMap; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.function.Function; | ||
import lombok.RequiredArgsConstructor; | ||
import org.apache.commons.lang3.tuple.Pair; | ||
|
||
/** | ||
* The Implementation of Content to represent {@link Object}. | ||
*/ | ||
@RequiredArgsConstructor | ||
public class ObjectContent implements Content { | ||
|
||
private final Object value; | ||
|
||
@Override | ||
public Integer intValue() { | ||
return parseNumberValue(value, Integer::valueOf, Number::intValue); | ||
} | ||
|
||
@Override | ||
public Long longValue() { | ||
return parseNumberValue(value, Long::valueOf, Number::longValue); | ||
} | ||
|
||
@Override | ||
public Short shortValue() { | ||
return parseNumberValue(value, Short::valueOf, Number::shortValue); | ||
} | ||
|
||
@Override | ||
public Byte byteValue() { | ||
return parseNumberValue(value, Byte::valueOf, Number::byteValue); | ||
} | ||
|
||
@Override | ||
public Float floatValue() { | ||
return parseNumberValue(value, Float::valueOf, Number::floatValue); | ||
} | ||
|
||
@Override | ||
public Double doubleValue() { | ||
return parseNumberValue(value, Double::valueOf, Number::doubleValue); | ||
} | ||
|
||
@Override | ||
public String stringValue() { | ||
return (String) value; | ||
} | ||
|
||
@Override | ||
public Boolean booleanValue() { | ||
return (Boolean) value; | ||
} | ||
|
||
@Override | ||
public Object objectValue() { | ||
return value; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
@Override | ||
public Iterator<Map.Entry<String, Content>> map() { | ||
return ((Map<String, Object>) value).entrySet().stream() | ||
.map(entry -> (Map.Entry<String, Content>) new AbstractMap.SimpleEntry<String, Content>( | ||
entry.getKey(), | ||
new ObjectContent(entry.getValue()))) | ||
.iterator(); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
@Override | ||
public Iterator<? extends Content> array() { | ||
return ((List<Object>) value).stream().map(ObjectContent::new).iterator(); | ||
} | ||
|
||
@Override | ||
public boolean isNull() { | ||
return value == null; | ||
} | ||
|
||
@Override | ||
public boolean isNumber() { | ||
return value instanceof Number; | ||
} | ||
|
||
@Override | ||
public boolean isString() { | ||
return value instanceof String; | ||
} | ||
|
||
@Override | ||
public Pair<Double, Double> geoValue() { | ||
final String[] split = ((String) value).split(","); | ||
return Pair.of(Double.valueOf(split[0]), Double.valueOf(split[1])); | ||
} | ||
|
||
private <T> T parseNumberValue(Object value, Function<String, T> stringTFunction, | ||
Function<Number, T> numberTFunction) { | ||
if (value instanceof String) { | ||
return stringTFunction.apply((String) value); | ||
} else { | ||
return numberTFunction.apply((Number) value); | ||
} | ||
} | ||
} |
Oops, something went wrong.