diff --git a/docs/en/docs/lakehouse/multi-catalog/es.md b/docs/en/docs/lakehouse/multi-catalog/es.md
index 580882f69b..6edbb95556 100644
--- a/docs/en/docs/lakehouse/multi-catalog/es.md
+++ b/docs/en/docs/lakehouse/multi-catalog/es.md
@@ -68,27 +68,28 @@ After switching to the ES Catalog, you will be in the `dafault_db` so you don't
## Column Type Mapping
-| ES Type | Doris Type | Comment |
-| ------------- | ----------- | ------- |
-| null | null | |
-| boolean | boolean | |
-| byte | tinyint | |
-| short | smallint | |
-| integer | int | |
-| long | bigint | |
-| unsigned_long | largeint | |
-| float | float | |
-| half_float | float | |
-| double | double | |
-| scaled_float | double | |
-| date | date | |
-| keyword | string | |
-| text | string | |
-| ip | string | |
-| nested | string | |
-| object | string | |
-| other | unsupported | |
+| ES Type | Doris Type | Comment |
+| ------------- | ----------- |-------------------------------------------------------------------------|
+| null | null | |
+| boolean | boolean | |
+| byte | tinyint | |
+| short | smallint | |
+| integer | int | |
+| long | bigint | |
+| unsigned_long | largeint | |
+| float | float | |
+| half_float | float | |
+| double | double | |
+| scaled_float | double | |
+| date | date | Only support default/yyyy-MM-dd HH:mm:ss/yyyy-MM-dd/epoch_millis format |
+| keyword | string | |
+| text | string | |
+| ip | string | |
+| nested | string | |
+| object | string | |
+| other | unsupported | |
+
### Array Type
Elasticsearch does not have an explicit array type, but one of its fields can contain
@@ -153,6 +154,7 @@ curl -X PUT "localhost:9200/doc/_mapping?pretty" -H 'Content-Type: application/j
`array_fields`:Used to indicate a field that is an array type.
+
## Best Practice
### Predicate Pushdown
diff --git a/docs/zh-CN/docs/lakehouse/multi-catalog/es.md b/docs/zh-CN/docs/lakehouse/multi-catalog/es.md
index b745a36d93..ec74f1207d 100644
--- a/docs/zh-CN/docs/lakehouse/multi-catalog/es.md
+++ b/docs/zh-CN/docs/lakehouse/multi-catalog/es.md
@@ -68,27 +68,28 @@ CREATE CATALOG es PROPERTIES (
## 列类型映射
-| ES Type | Doris Type | Comment |
-|---|---|---|
+| ES Type | Doris Type | Comment |
+|---|---|------------------------------------------------------------|
|null| null||
-| boolean | boolean | |
-| byte| tinyint| |
-| short| smallint| |
-| integer| int| |
-| long| bigint| |
-| unsigned_long| largeint | |
-| float| float| |
-| half_float| float| |
-| double | double | |
-| scaled_float| double | |
-| date | date | |
-| keyword | string | |
-| text |string | |
-| ip |string | |
-| nested |string | |
-| object |string | |
+| boolean | boolean | |
+| byte| tinyint| |
+| short| smallint| |
+| integer| int| |
+| long| bigint| |
+| unsigned_long| largeint | |
+| float| float| |
+| half_float| float| |
+| double | double | |
+| scaled_float| double | |
+| date | date | 仅支持 default/yyyy-MM-dd HH:mm:ss/yyyy-MM-dd/epoch_millis 格式 |
+| keyword | string | |
+| text |string | |
+| ip |string | |
+| nested |string | |
+| object |string | |
|other| unsupported ||
+
### Array 类型
Elasticsearch 没有明确的数组类型,但是它的某个字段可以含有[0个或多个值](https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html)。
@@ -148,6 +149,7 @@ curl -X PUT "localhost:9200/doc/_mapping?pretty" -H 'Content-Type: application/j
`array_fields`:用来表示是数组类型的字段。
+
## 最佳实践
### 过滤条件下推
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/EsTable.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/EsTable.java
index 81000c69d1..5d77163857 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/EsTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/EsTable.java
@@ -145,6 +145,10 @@ public class EsTable extends Table {
return esMetaStateTracker.searchContext().docValueFieldsContext();
}
+ public List needCompatDateFields() {
+ return esMetaStateTracker.searchContext().needCompatDateFields();
+ }
+
private void validate(Map properties) throws DdlException {
EsResource.valid(properties, false);
hosts = properties.get(EsResource.HOSTS).trim();
@@ -270,10 +274,10 @@ public class EsTable extends Table {
indexName = tableContext.get("indexName");
mappingType = tableContext.get("mappingType");
- enableDocValueScan = Boolean.parseBoolean(tableContext.getOrDefault("enableDocValueScan",
- EsResource.DOC_VALUE_SCAN_DEFAULT_VALUE));
- enableKeywordSniff = Boolean.parseBoolean(tableContext.getOrDefault("enableKeywordSniff",
- EsResource.KEYWORD_SNIFF_DEFAULT_VALUE));
+ enableDocValueScan = Boolean.parseBoolean(
+ tableContext.getOrDefault("enableDocValueScan", EsResource.DOC_VALUE_SCAN_DEFAULT_VALUE));
+ enableKeywordSniff = Boolean.parseBoolean(
+ tableContext.getOrDefault("enableKeywordSniff", EsResource.KEYWORD_SNIFF_DEFAULT_VALUE));
if (tableContext.containsKey("maxDocValueFields")) {
try {
maxDocValueFields = Integer.parseInt(tableContext.get("maxDocValueFields"));
@@ -281,12 +285,12 @@ public class EsTable extends Table {
maxDocValueFields = DEFAULT_MAX_DOCVALUE_FIELDS;
}
}
- nodesDiscovery = Boolean.parseBoolean(tableContext.getOrDefault(EsResource.NODES_DISCOVERY,
- EsResource.NODES_DISCOVERY_DEFAULT_VALUE));
- httpSslEnabled = Boolean.parseBoolean(tableContext.getOrDefault(EsResource.HTTP_SSL_ENABLED,
- EsResource.HTTP_SSL_ENABLED_DEFAULT_VALUE));
- likePushDown = Boolean.parseBoolean(tableContext.getOrDefault(EsResource.LIKE_PUSH_DOWN,
- EsResource.LIKE_PUSH_DOWN_DEFAULT_VALUE));
+ nodesDiscovery = Boolean.parseBoolean(
+ tableContext.getOrDefault(EsResource.NODES_DISCOVERY, EsResource.NODES_DISCOVERY_DEFAULT_VALUE));
+ httpSslEnabled = Boolean.parseBoolean(
+ tableContext.getOrDefault(EsResource.HTTP_SSL_ENABLED, EsResource.HTTP_SSL_ENABLED_DEFAULT_VALUE));
+ likePushDown = Boolean.parseBoolean(
+ tableContext.getOrDefault(EsResource.LIKE_PUSH_DOWN, EsResource.LIKE_PUSH_DOWN_DEFAULT_VALUE));
PartitionType partType = PartitionType.valueOf(Text.readString(in));
if (partType == PartitionType.UNPARTITIONED) {
partitionInfo = SinglePartitionInfo.read(in);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/util/JsonUtil.java b/fe/fe-core/src/main/java/org/apache/doris/common/util/JsonUtil.java
index 1cd52b5067..d1eccaeb4e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/util/JsonUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/util/JsonUtil.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -63,6 +64,17 @@ public class JsonUtil {
}
}
+ /**
+ * Parse json text to ObjectNode
+ **/
+ public static ObjectNode parseObject(String text) {
+ try {
+ return (ObjectNode) objectMapper.readTree(text);
+ } catch (Exception e) {
+ throw new RuntimeException("parseObject exception.", e);
+ }
+ }
+
public static T readValue(String text, Class clazz) throws JsonProcessingException {
return objectMapper.readValue(text, clazz);
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java
index c2447c8428..1357608eb2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/EsUtil.java
@@ -26,17 +26,19 @@ import org.apache.doris.catalog.ScalarType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.DdlException;
+import org.apache.doris.common.util.JsonUtil;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.json.simple.JSONObject;
-import org.json.simple.JSONValue;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Util for ES, some static method.
@@ -78,28 +80,6 @@ public class EsUtil {
}
}
-
- /**
- * Get the json object from specified jsonObject
- */
- public static JSONObject getJsonObject(JSONObject jsonObject, String key, int fromIndex) {
- int firstOccr = key.indexOf('.', fromIndex);
- if (firstOccr == -1) {
- String token = key.substring(key.lastIndexOf('.') + 1);
- if (jsonObject.containsKey(token)) {
- return (JSONObject) jsonObject.get(token);
- } else {
- return null;
- }
- }
- String fieldName = key.substring(fromIndex, firstOccr);
- if (jsonObject.containsKey(fieldName)) {
- return getJsonObject((JSONObject) jsonObject.get(fieldName), key, firstOccr + 1);
- } else {
- return null;
- }
- }
-
/**
* Get boolean throw DdlException when parse error
**/
@@ -113,46 +93,15 @@ public class EsUtil {
}
}
- /**
- * Get Array fields.
- **/
- public static List getArrayFields(String indexMapping) {
- JSONObject mappings = getMapping(indexMapping);
- JSONObject meta;
- if (!mappings.containsKey("_meta")) {
- // For ES 6.x and 7.x
- String firstType = (String) mappings.keySet().iterator().next();
- if (!"properties".equals(firstType)) {
- // If type is not passed in takes the first type.
- JSONObject firstData = (JSONObject) mappings.get(firstType);
- if (!firstData.containsKey("_meta")) {
- return new ArrayList<>();
- } else {
- meta = (JSONObject) firstData.get("_meta");
- }
- } else {
- return new ArrayList<>();
- }
- } else {
- meta = (JSONObject) mappings.get("_meta");
- }
- if (!meta.containsKey("doris")) {
- return new ArrayList<>();
- }
- JSONObject dorisMeta = (JSONObject) meta.get("doris");
- return (List) dorisMeta.get("array_fields");
- }
-
- private static JSONObject getMapping(String indexMapping) {
- JSONObject jsonObject = (JSONObject) JSONValue.parse(indexMapping);
+ @VisibleForTesting
+ public static ObjectNode getMapping(String indexMapping) {
+ ObjectNode jsonNodes = JsonUtil.parseObject(indexMapping);
// If the indexName use alias takes the first mapping
- Iterator keys = jsonObject.keySet().iterator();
- String docKey = keys.next();
- JSONObject docData = (JSONObject) jsonObject.get(docKey);
- return (JSONObject) docData.get("mappings");
+ return (ObjectNode) jsonNodes.iterator().next().get("mappings");
}
- private static JSONObject getRootSchema(JSONObject mappings, String mappingType) {
+ @VisibleForTesting
+ public static ObjectNode getRootSchema(ObjectNode mappings, String mappingType) {
// Type is null in the following three cases
// 1. Equal 6.8.x and after
// 2. Multi-catalog auto infer
@@ -160,10 +109,10 @@ public class EsUtil {
if (mappingType == null) {
// remove dynamic templates, for ES 7.x and 8.x
checkNonPropertiesFields(mappings);
- String firstType = (String) mappings.keySet().iterator().next();
+ String firstType = mappings.fieldNames().next();
if (!"properties".equals(firstType)) {
// If type is not passed in takes the first type.
- JSONObject firstData = (JSONObject) mappings.get(firstType);
+ ObjectNode firstData = (ObjectNode) mappings.get(firstType);
// check for ES 6.x and before
checkNonPropertiesFields(firstData);
return firstData;
@@ -171,8 +120,8 @@ public class EsUtil {
// Equal 7.x and after
return mappings;
} else {
- if (mappings.containsKey(mappingType)) {
- JSONObject jsonData = (JSONObject) mappings.get(mappingType);
+ if (mappings.has(mappingType)) {
+ ObjectNode jsonData = (ObjectNode) mappings.get(mappingType);
// check for ES 6.x and before
checkNonPropertiesFields(jsonData);
return jsonData;
@@ -187,7 +136,7 @@ public class EsUtil {
*
* @param mappings
*/
- private static void checkNonPropertiesFields(JSONObject mappings) {
+ private static void checkNonPropertiesFields(ObjectNode mappings) {
// remove `_meta` field
mappings.remove("_meta");
// remove `dynamic_templates` field
@@ -199,12 +148,12 @@ public class EsUtil {
}
/**
- * Get mapping properties JSONObject.
+ * Get mapping properties transform to ObjectNode.
**/
- public static JSONObject getMappingProps(String sourceIndex, String indexMapping, String mappingType) {
- JSONObject mappings = getMapping(indexMapping);
- JSONObject rootSchema = getRootSchema(mappings, mappingType);
- JSONObject properties = (JSONObject) rootSchema.get("properties");
+ public static ObjectNode getMappingProps(String sourceIndex, String indexMapping, String mappingType) {
+ ObjectNode mappings = getMapping(indexMapping);
+ ObjectNode rootSchema = getRootSchema(mappings, mappingType);
+ ObjectNode properties = (ObjectNode) rootSchema.get("properties");
if (properties == null) {
throw new DorisEsException(
"index[" + sourceIndex + "] type[" + mappingType + "] mapping not found for the ES Cluster");
@@ -212,7 +161,6 @@ public class EsUtil {
return properties;
}
-
/**
* Generate columns from ES Cluster.
* Add mappingEsId config in es external catalog.
@@ -220,9 +168,14 @@ public class EsUtil {
public static List genColumnsFromEs(EsRestClient client, String indexName, String mappingType,
boolean mappingEsId) {
String mapping = client.getMapping(indexName);
- JSONObject mappingProps = getMappingProps(indexName, mapping, mappingType);
- List arrayFields = getArrayFields(mapping);
- Set keys = (Set) mappingProps.keySet();
+ ObjectNode mappings = getMapping(mapping);
+ ObjectNode rootSchema = getRootSchema(mappings, mappingType);
+ return genColumnsFromEs(indexName, mappingType, rootSchema, mappingEsId);
+ }
+
+ @VisibleForTesting
+ public static List genColumnsFromEs(String indexName, String mappingType, ObjectNode rootSchema,
+ boolean mappingEsId) {
List columns = new ArrayList<>();
if (mappingEsId) {
Column column = new Column();
@@ -233,68 +186,143 @@ public class EsUtil {
column.setUniqueId(-1);
columns.add(column);
}
- for (String key : keys) {
- JSONObject field = (JSONObject) mappingProps.get(key);
- Type type;
- // Complex types are treating as String types for now.
- if (field.containsKey("type")) {
- type = toDorisType(field.get("type").toString());
- } else {
- type = Type.STRING;
- }
- Column column = new Column();
- column.setName(key);
- column.setIsKey(true);
- column.setIsAllowNull(true);
- column.setUniqueId(-1);
- if (arrayFields.contains(key)) {
- column.setType(ArrayType.create(type, true));
- } else {
- column.setType(type);
+ ObjectNode mappingProps = (ObjectNode) rootSchema.get("properties");
+ if (mappingProps == null) {
+ throw new DorisEsException(
+ "index[" + indexName + "] type[" + mappingType + "] mapping not found for the ES Cluster");
+ }
+ List arrayFields = new ArrayList<>();
+ JsonNode meta = mappingProps.get("_meta");
+ if (meta != null) {
+ JsonNode dorisMeta = meta.get("doris");
+ if (dorisMeta != null) {
+ arrayFields = dorisMeta.findValuesAsText("array_fields");
}
+ }
+ Iterator iterator = mappingProps.fieldNames();
+ while (iterator.hasNext()) {
+ String fieldName = iterator.next();
+ ObjectNode fieldValue = (ObjectNode) mappingProps.get(fieldName);
+ Column column = parseEsField(fieldName, fieldValue, arrayFields);
columns.add(column);
}
return columns;
}
- /**
- * Transfer es type to doris type.
- **/
- public static Type toDorisType(String esType) {
- // reference https://www.elastic.co/guide/en/elasticsearch/reference/8.3/sql-data-types.html
- switch (esType) {
- case "null":
- return Type.NULL;
- case "boolean":
- return Type.BOOLEAN;
- case "byte":
- return Type.TINYINT;
- case "short":
- return Type.SMALLINT;
- case "integer":
- return Type.INT;
- case "long":
- return Type.BIGINT;
- case "unsigned_long":
- return Type.LARGEINT;
- case "float":
- case "half_float":
- return Type.FLOAT;
- case "double":
- case "scaled_float":
- return Type.DOUBLE;
- case "date":
- return ScalarType.createDateV2Type();
- case "keyword":
- case "text":
- case "ip":
- case "nested":
- case "object":
- return ScalarType.createStringType();
- default:
- return Type.UNSUPPORTED;
+ private static Column parseEsField(String fieldName, ObjectNode fieldValue, List arrayFields) {
+ Column column = new Column();
+ column.setName(fieldName);
+ column.setIsKey(true);
+ column.setIsAllowNull(true);
+ column.setUniqueId(-1);
+ Type type;
+ // Complex types are treating as String types for now.
+ if (fieldValue.has("type")) {
+ String typeStr = fieldValue.get("type").asText();
+ column.setComment("Elasticsearch type is " + typeStr);
+ // reference https://www.elastic.co/guide/en/elasticsearch/reference/8.3/sql-data-types.html
+ switch (typeStr) {
+ case "null":
+ type = Type.NULL;
+ break;
+ case "boolean":
+ type = Type.BOOLEAN;
+ break;
+ case "byte":
+ type = Type.TINYINT;
+ break;
+ case "short":
+ type = Type.SMALLINT;
+ break;
+ case "integer":
+ type = Type.INT;
+ break;
+ case "long":
+ type = Type.BIGINT;
+ break;
+ case "unsigned_long":
+ type = Type.LARGEINT;
+ break;
+ case "float":
+ case "half_float":
+ type = Type.FLOAT;
+ break;
+ case "double":
+ case "scaled_float":
+ type = Type.DOUBLE;
+ break;
+ case "date":
+ type = parseEsDateType(column, fieldValue);
+ break;
+ case "keyword":
+ case "text":
+ case "ip":
+ case "nested":
+ case "object":
+ type = ScalarType.createStringType();
+ break;
+ default:
+ type = Type.UNSUPPORTED;
+ }
+ } else {
+ type = Type.STRING;
+ column.setComment("Elasticsearch no type");
}
+ if (arrayFields.contains(fieldName)) {
+ column.setType(ArrayType.create(type, true));
+ } else {
+ column.setType(type);
+ }
+ return column;
}
-}
+ private static final List ALLOW_DATE_FORMATS = Lists.newArrayList("yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd",
+ "epoch_millis");
+ /**
+ * Parse es date to doris type by format
+ **/
+ private static Type parseEsDateType(Column column, ObjectNode field) {
+ if (!field.has("format")) {
+ // default format
+ column.setComment("Elasticsearch type is date, no format");
+ return ScalarType.createDatetimeV2Type(0);
+ } else {
+ String originFormat = field.get("format").asText();
+ String[] formats = originFormat.split("\\|\\|");
+ boolean dateTimeFlag = false;
+ boolean dateFlag = false;
+ boolean bigIntFlag = false;
+ for (String format : formats) {
+ // pre-check format
+ if (!ALLOW_DATE_FORMATS.contains(format)) {
+ column.setComment(
+ "Elasticsearch type is date, format is " + format + " not support, use String type");
+ return ScalarType.createStringType();
+ }
+ switch (format) {
+ case "yyyy-MM-dd HH:mm:ss":
+ dateTimeFlag = true;
+ break;
+ case "yyyy-MM-dd":
+ dateFlag = true;
+ break;
+ case "epoch_millis":
+ default:
+ bigIntFlag = true;
+ }
+ }
+ column.setComment("Elasticsearch type is date, format is " + originFormat);
+ if (dateTimeFlag) {
+ return ScalarType.createDatetimeV2Type(0);
+ }
+ if (dateFlag) {
+ return ScalarType.createDateV2Type();
+ }
+ if (bigIntFlag) {
+ return Type.BIGINT;
+ }
+ return ScalarType.createStringType();
+ }
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/MappingPhase.java b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/MappingPhase.java
index 42500d7f96..26d1bc1dcc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/MappingPhase.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/MappingPhase.java
@@ -20,8 +20,11 @@ package org.apache.doris.external.elasticsearch;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.EsTable;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
-import org.json.simple.JSONObject;
+
+import java.util.Iterator;
/**
* Get index mapping from remote ES Cluster, and resolved `keyword` and `doc_values` field
@@ -55,69 +58,88 @@ public class MappingPhase implements SearchPhase {
* @param indexMapping the return value of _mapping
*/
public static void resolveFields(SearchContext searchContext, String indexMapping) throws DorisEsException {
- JSONObject properties = EsUtil.getMappingProps(searchContext.sourceIndex(), indexMapping, searchContext.type());
+ ObjectNode properties = EsUtil.getMappingProps(searchContext.sourceIndex(), indexMapping, searchContext.type());
for (Column col : searchContext.columns()) {
String colName = col.getName();
// _id not exist mapping, but be can query it.
if (!"_id".equals(colName)) {
- if (!properties.containsKey(colName)) {
+ if (!properties.has(colName)) {
throw new DorisEsException(
"index[" + searchContext.sourceIndex() + "] mapping[" + indexMapping + "] not found "
+ "column " + colName + " for the ES Cluster");
}
- JSONObject fieldObject = (JSONObject) properties.get(colName);
- resolveKeywordFields(searchContext, fieldObject, colName);
- resolveDocValuesFields(searchContext, fieldObject, colName);
+ ObjectNode fieldObject = (ObjectNode) properties.get(colName);
+ if (!fieldObject.has("type")) {
+ continue;
+ }
+ String fieldType = fieldObject.get("type").asText();
+ resolveDateFields(searchContext, fieldObject, colName, fieldType);
+ resolveKeywordFields(searchContext, fieldObject, colName, fieldType);
+ resolveDocValuesFields(searchContext, fieldObject, colName, fieldType);
+ }
+ }
+ }
+
+ private static void resolveDateFields(SearchContext searchContext, ObjectNode fieldObject, String colName,
+ String fieldType) {
+ // Compat use default/strict_date_optional_time format date type, need transform datetime to
+ if ("date".equals(fieldType)) {
+ if (!fieldObject.has("format") || "strict_date_optional_time".equals(fieldObject.get("format").asText())) {
+ searchContext.needCompatDateFields().add(colName);
}
}
}
// get a field of keyword type in the fields
- private static void resolveKeywordFields(SearchContext searchContext, JSONObject fieldObject, String colName) {
- String fieldType = (String) fieldObject.get("type");
+ private static void resolveKeywordFields(SearchContext searchContext, ObjectNode fieldObject, String colName,
+ String fieldType) {
// string-type field used keyword type to generate predicate
// if text field type seen, we should use the `field` keyword type?
if ("text".equals(fieldType)) {
- JSONObject fieldsObject = (JSONObject) fieldObject.get("fields");
+ JsonNode fieldsObject = fieldObject.get("fields");
if (fieldsObject != null) {
- for (Object key : fieldsObject.keySet()) {
- JSONObject innerTypeObject = (JSONObject) fieldsObject.get(key);
+ Iterator fieldNames = fieldsObject.fieldNames();
+ while (fieldNames.hasNext()) {
+ String fieldName = fieldNames.next();
+ ObjectNode innerTypeObject = (ObjectNode) fieldsObject.get(fieldName);
// just for text type
- if ("keyword".equals(innerTypeObject.get("type"))) {
- searchContext.fetchFieldsContext().put(colName, colName + "." + key);
+ if ("keyword".equals(innerTypeObject.get("type").asText())) {
+ searchContext.fetchFieldsContext().put(colName, colName + "." + fieldName);
}
}
}
}
}
- private static void resolveDocValuesFields(SearchContext searchContext, JSONObject fieldObject, String colName) {
- String fieldType = (String) fieldObject.get("type");
+ private static void resolveDocValuesFields(SearchContext searchContext, ObjectNode fieldObject, String colName,
+ String fieldType) {
String docValueField = null;
if (EsTable.DEFAULT_DOCVALUE_DISABLED_FIELDS.contains(fieldType)) {
- JSONObject fieldsObject = (JSONObject) fieldObject.get("fields");
+ JsonNode fieldsObject = fieldObject.get("fields");
if (fieldsObject != null) {
- for (Object key : fieldsObject.keySet()) {
- JSONObject innerTypeObject = (JSONObject) fieldsObject.get((String) key);
- if (EsTable.DEFAULT_DOCVALUE_DISABLED_FIELDS.contains((String) innerTypeObject.get("type"))) {
+ Iterator fieldNames = fieldsObject.fieldNames();
+ while (fieldNames.hasNext()) {
+ String fieldName = fieldNames.next();
+ ObjectNode innerTypeObject = (ObjectNode) fieldsObject.get(fieldName);
+ if (EsTable.DEFAULT_DOCVALUE_DISABLED_FIELDS.contains(innerTypeObject.get("type").asText())) {
continue;
}
- if (innerTypeObject.containsKey("doc_values")) {
- boolean docValue = (Boolean) innerTypeObject.get("doc_values");
+ if (innerTypeObject.has("doc_values")) {
+ boolean docValue = innerTypeObject.get("doc_values").asBoolean();
if (docValue) {
docValueField = colName;
}
} else {
// a : {c : {}} -> a -> a.c
- docValueField = colName + "." + key;
+ docValueField = colName + "." + fieldName;
}
}
}
} else {
// set doc_value = false manually
- if (fieldObject.containsKey("doc_values")) {
- Boolean docValue = (Boolean) fieldObject.get("doc_values");
+ if (fieldObject.has("doc_values")) {
+ boolean docValue = fieldObject.get("doc_values").asBoolean();
if (!docValue) {
return;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/QueryBuilders.java b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/QueryBuilders.java
index cc269a452a..a0a805747a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/QueryBuilders.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/external/elasticsearch/QueryBuilders.java
@@ -42,6 +42,9 @@ import lombok.Builder;
import lombok.Data;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
import java.io.IOException;
import java.io.StringWriter;
@@ -123,8 +126,12 @@ public final class QueryBuilders {
.build());
}
- private static QueryBuilder parseBinaryPredicate(Expr expr, TExprOpcode opCode, String column) {
+ private static QueryBuilder parseBinaryPredicate(Expr expr, TExprOpcode opCode, String column,
+ boolean needDateCompat) {
Object value = toDorisLiteral(expr.getChild(1));
+ if (needDateCompat) {
+ value = compatDefaultDate(value);
+ }
switch (opCode) {
case EQ:
case EQ_FOR_NULL:
@@ -180,10 +187,14 @@ public final class QueryBuilders {
}
}
- private static QueryBuilder parseInPredicate(Expr expr, String column) {
+ private static QueryBuilder parseInPredicate(Expr expr, String column, boolean needDateCompat) {
InPredicate inPredicate = (InPredicate) expr;
- List