You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ar...@apache.org on 2021/02/17 08:11:24 UTC
[metamodel] 03/05: MM-1233: Refactoring, DIFFERENT_FROM operator.
This is an automated email from the ASF dual-hosted git repository.
arjansh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/metamodel.git
commit 142c4ae09f55af87fd15a66af78c887a663e4252
Author: jakub <j....@quadient.com>
AuthorDate: Mon Feb 15 13:43:20 2021 +0100
MM-1233: Refactoring, DIFFERENT_FROM operator.
---
.../elasticsearch/common/ElasticSearchUtils.java | 118 ++++++++++++---------
.../common/ElasticSearchUtilsTest.java | 27 ++++-
2 files changed, 92 insertions(+), 53 deletions(-)
diff --git a/elasticsearch/common/src/main/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtils.java b/elasticsearch/common/src/main/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtils.java
index 5458174..d051c32 100644
--- a/elasticsearch/common/src/main/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtils.java
+++ b/elasticsearch/common/src/main/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtils.java
@@ -170,63 +170,18 @@ public class ElasticSearchUtils {
* @return a {@link QueryBuilder} if one was produced, or null if the items
* could not be pushed down to an ElasticSearch query
*/
- public static QueryBuilder createQueryBuilderForSimpleWhere(List<FilterItem> whereItems,
- LogicalOperator logicalOperator) {
+ public static QueryBuilder createQueryBuilderForSimpleWhere(final List<FilterItem> whereItems,
+ final LogicalOperator logicalOperator) {
if (whereItems.isEmpty()) {
return QueryBuilders.matchAllQuery();
}
- List<QueryBuilder> children = new ArrayList<>(whereItems.size());
- for (FilterItem item : whereItems) {
- final QueryBuilder itemQueryBuilder;
-
- if (item.isCompoundFilter()) {
- final List<FilterItem> childItems = Arrays.asList(item.getChildItems());
- itemQueryBuilder = createQueryBuilderForSimpleWhere(childItems, item.getLogicalOperator());
- if (itemQueryBuilder == null) {
- // something was not supported, so we have to forfeit here
- // too.
- return null;
- }
- } else {
- final Column column = item.getSelectItem().getColumn();
- if (column == null) {
- // unsupported type of where item - must have a column
- // reference
- return null;
- }
- final String fieldName = column.getName();
- final Object operand = item.getOperand();
- final OperatorType operator = item.getOperator();
-
- if (OperatorType.EQUALS_TO.equals(operator)) {
- if (operand == null) {
- itemQueryBuilder = getMissingQuery(fieldName);
- } else if (column.getType().isLiteral()) {
- itemQueryBuilder = QueryBuilders.matchQuery(fieldName, operand);
- } else {
- itemQueryBuilder = QueryBuilders.termQuery(fieldName, operand);
- }
- } else if (OperatorType.DIFFERENT_FROM.equals(operator)) {
- if (operand == null) {
- itemQueryBuilder = getExistsQuery(fieldName);
- } else {
- itemQueryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.termQuery(fieldName,
- operand));
- }
- } else if (OperatorType.IN.equals(operator)) {
- final List<?> operands = CollectionUtils.toList(operand);
- if (column.getType().isLiteral()) {
- itemQueryBuilder = QueryBuilders.termQuery(fieldName, operand);
- } else {
- itemQueryBuilder = QueryBuilders.termsQuery(fieldName, operands);
- }
- } else {
- // not (yet) support operator types
- return null;
- }
+ final List<QueryBuilder> children = new ArrayList<>(whereItems.size());
+ for (final FilterItem item : whereItems) {
+ final QueryBuilder itemQueryBuilder = createFilterItemQueryBuilder(item);
+ if (itemQueryBuilder == null) {
+ return null;
}
-
children.add(itemQueryBuilder);
}
@@ -249,6 +204,65 @@ public class ElasticSearchUtils {
return result;
}
+ private static QueryBuilder createFilterItemQueryBuilder(final FilterItem filterItem) {
+ final QueryBuilder itemQueryBuilder;
+ if (filterItem.isCompoundFilter()) {
+ final List<FilterItem> childItems = Arrays.asList(filterItem.getChildItems());
+ itemQueryBuilder = createQueryBuilderForSimpleWhere(childItems, filterItem.getLogicalOperator());
+ } else {
+ final Column column = filterItem.getSelectItem().getColumn();
+ if (column == null) {
+ // unsupported type of where item - must have a column reference
+ return null;
+ }
+ itemQueryBuilder = createQueryBuilderForOperator(filterItem, column);
+ }
+
+ return itemQueryBuilder;
+ }
+
+ private static QueryBuilder createQueryBuilderForOperator(final FilterItem filterItem, final Column column) {
+ if (OperatorType.EQUALS_TO.equals(filterItem.getOperator())) {
+ if (filterItem.getOperand() == null) {
+ return getMissingQuery(column.getName());
+ } else {
+ return matchOrTermQuery(column, filterItem.getOperand());
+ }
+ } else if (OperatorType.DIFFERENT_FROM.equals(filterItem.getOperator())) {
+ if (filterItem.getOperand() == null) {
+ return getExistsQuery(column.getName());
+ } else {
+ return QueryBuilders.boolQuery().mustNot(matchOrTermQuery(column, filterItem.getOperand()));
+ }
+ } else if (OperatorType.IN.equals(filterItem.getOperator())) {
+ final List<?> operands = CollectionUtils.toList(filterItem.getOperand());
+ if (column.getType().isLiteral()) {
+ return createMultipleValuesQueryBuilder(column.getName(), operands);
+ } else {
+ return QueryBuilders.termsQuery(column.getName(), operands);
+ }
+ } else {
+ // not (yet) supported operator types
+ return null;
+ }
+ }
+
+ private static QueryBuilder matchOrTermQuery(final Column column, final Object operand) {
+ if (column.getType().isLiteral()) {
+ return QueryBuilders.matchQuery(column.getName(), operand);
+ } else {
+ return QueryBuilders.termQuery(column.getName(), operand);
+ }
+ }
+
+ private static QueryBuilder createMultipleValuesQueryBuilder(final String columnName, final List<?> operands) {
+ final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+ for (final Object value : operands) {
+ boolQueryBuilder.should(QueryBuilders.matchQuery(columnName, value.toString()));
+ }
+ return boolQueryBuilder;
+ }
+
public static ColumnType getColumnTypeFromElasticSearchType(final String metaDataFieldType) {
final ColumnType columnType;
if (metaDataFieldType.startsWith("date")) {
diff --git a/elasticsearch/common/src/test/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtilsTest.java b/elasticsearch/common/src/test/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtilsTest.java
index 8228316..4d18b27 100644
--- a/elasticsearch/common/src/test/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtilsTest.java
+++ b/elasticsearch/common/src/test/java/org/apache/metamodel/elasticsearch/common/ElasticSearchUtilsTest.java
@@ -73,11 +73,36 @@ public class ElasticSearchUtilsTest extends TestCase {
/**
* For text-based conditions a 'match' query is recommended (instead of 'term' query).
*/
- public void testMatchQueryIsCreatedForTextFilter() {
+ public void testMatchQueryIsCreatedForTextEqualTo() {
final SelectItem selectItem = new SelectItem(new MutableColumn("column_name", ColumnType.STRING));
final FilterItem filterItem = new FilterItem(selectItem, OperatorType.EQUALS_TO, "text-value");
final QueryBuilder queryBuilder =
ElasticSearchUtils.createQueryBuilderForSimpleWhere(Collections.singletonList(filterItem), null);
assertEquals("match", queryBuilder.getName());
}
+
+ /**
+ * For text-based conditions a 'match' query is recommended (instead of 'term' query).
+ * In case of 'DIFFERENT_FROM', we need a 'bool' query with 'must not' and 'match' query.
+ */
+ public void testBoolQueryIsCreatedForTextDifferentFrom() {
+ final SelectItem selectItem = new SelectItem(new MutableColumn("column_name", ColumnType.STRING));
+ final FilterItem filterItem = new FilterItem(selectItem, OperatorType.DIFFERENT_FROM, "text-value");
+ final QueryBuilder queryBuilder =
+ ElasticSearchUtils.createQueryBuilderForSimpleWhere(Collections.singletonList(filterItem), null);
+ assertEquals("bool", queryBuilder.getName());
+ }
+
+ /**
+ * For text-based conditions a 'match' query is recommended (instead of 'term' query).
+ * To simulate 'IN' operator, we need a 'bool' query with multiple 'match' queries combined with 'OR'.
+ */
+ public void testBoolQueryIsCreatedForTextIn() {
+ final SelectItem selectItem = new SelectItem(new MutableColumn("column_name", ColumnType.STRING));
+ final FilterItem filterItem =
+ new FilterItem(selectItem, OperatorType.IN, Arrays.asList("text-value-a", "text-value-b"));
+ final QueryBuilder queryBuilder =
+ ElasticSearchUtils.createQueryBuilderForSimpleWhere(Collections.singletonList(filterItem), null);
+ assertEquals("bool", queryBuilder.getName());
+ }
}