Commit e5037282 by Pinal Shah Committed by kevalbhatt

ATLAS-3600 : Some System Attribute of Entity filter doesn't work

Signed-off-by: 's avatarkevalbhatt <kbhatt@apache.org>
parent 668addac
......@@ -455,6 +455,7 @@ public class SearchParameters implements Serializable {
STARTS_WITH(new String[]{"startsWith", "STARTSWITH", "begins_with", "BEGINS_WITH"}),
ENDS_WITH(new String[]{"endsWith", "ENDSWITH", "ends_with", "ENDS_WITH"}),
CONTAINS(new String[]{"contains", "CONTAINS"}),
NOT_CONTAINS(new String[]{"not_contains", "NOT_CONTAINS"}),
CONTAINS_ANY(new String[]{"containsAny", "CONTAINSANY", "contains_any", "CONTAINS_ANY"}),
CONTAINS_ALL(new String[]{"containsAll", "CONTAINSALL", "contains_all", "CONTAINS_ALL"}),
IS_NULL(new String[]{"isNull", "ISNULL", "is_null", "IS_NULL"}),
......
......@@ -310,6 +310,11 @@ public class EntitySearchProcessor extends SearchProcessor {
getVertices(queryResult, entityVertices);
isLastResultPage = entityVertices.size() < limit;
//incase when operator is NEQ in pipeSeperatedSystemAttributes
if (graphQueryPredicate != null) {
CollectionUtils.filter(entityVertices, graphQueryPredicate);
}
}
super.filter(entityVertices);
......
......@@ -25,6 +25,7 @@ import org.apache.atlas.model.discovery.SearchParameters.FilterCriteria;
import org.apache.atlas.model.discovery.SearchParameters.FilterCriteria.Condition;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.AtlasIndexQuery;
import org.apache.atlas.repository.graphdb.AtlasVertex;
......@@ -51,6 +52,7 @@ import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_CLASSIFIED;
import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_NOT_CLASSIFIED;
import static org.apache.atlas.discovery.SearchContext.MATCH_ALL_WILDCARD_CLASSIFICATION;
import static org.apache.atlas.repository.Constants.CLASSIFICATION_NAMES_KEY;
import static org.apache.atlas.repository.Constants.CLASSIFICATION_NAME_DELIMITER;
import static org.apache.atlas.repository.Constants.CUSTOM_ATTRIBUTES_PROPERTY_KEY;
import static org.apache.atlas.repository.Constants.LABELS_PROPERTY_KEY;
import static org.apache.atlas.repository.Constants.PROPAGATED_CLASSIFICATION_NAMES_KEY;
......@@ -76,6 +78,7 @@ public abstract class SearchProcessor {
public static final String ALL_TYPE_QUERY = "[* TO *]";
public static final char CUSTOM_ATTR_SEPARATOR = '=';
public static final String CUSTOM_ATTR_SEARCH_FORMAT = "\"\\\"%s\\\":\\\"%s\\\"\"";
public static final String CUSTOM_ATTR_SEARCH_FORMAT_GRAPH = "\"%s\":\"%s\"";
private static final Map<SearchParameters.Operator, String> OPERATOR_MAP = new HashMap<>();
private static final Map<SearchParameters.Operator, VertexAttributePredicateGenerator> OPERATOR_PREDICATE_MAP = new HashMap<>();
......@@ -115,6 +118,8 @@ public abstract class SearchProcessor {
OPERATOR_MAP.put(SearchParameters.Operator.CONTAINS, INDEX_SEARCH_PREFIX + "\"%s\": (*%s*)");
OPERATOR_PREDICATE_MAP.put(SearchParameters.Operator.CONTAINS, getContainsPredicateGenerator());
OPERATOR_PREDICATE_MAP.put(SearchParameters.Operator.NOT_CONTAINS, getNotContainsPredicateGenerator());
// TODO: Add contains any, contains all mappings here
OPERATOR_MAP.put(SearchParameters.Operator.IS_NULL, "(*:* NOT " + INDEX_SEARCH_PREFIX + "\"%s\":[* TO *])");
......@@ -481,13 +486,64 @@ public abstract class SearchProcessor {
return PredicateUtils.anyPredicate(predicates);
}
}
} else if (indexAttributes.contains(criteria.getAttributeName()) && !isPipeSeparatedSystemAttribute(criteria.getAttributeName())){
return toInMemoryPredicate(type, criteria.getAttributeName(), criteria.getOperator(), criteria.getAttributeValue());
} else if (indexAttributes.contains(criteria.getAttributeName())) {
String attrName = criteria.getAttributeName();
String attrValue = criteria.getAttributeValue();
SearchParameters.Operator operator = criteria.getOperator();
//process attribute value and attribute operator for pipeSeperated fields
if (isPipeSeparatedSystemAttribute(attrName)) {
FilterCriteria processedCriteria = processPipeSeperatedSystemAttribute(attrName, operator, attrValue);
attrValue = processedCriteria.getAttributeValue();
operator = processedCriteria.getOperator();
}
return toInMemoryPredicate(type, attrName, operator, attrValue);
}
return null;
}
private FilterCriteria processPipeSeperatedSystemAttribute(String attrName, SearchParameters.Operator op, String attrVal) {
FilterCriteria ret = new FilterCriteria();
if (op != null && attrVal != null) {
switch (op) {
case STARTS_WITH:
attrVal = CLASSIFICATION_NAME_DELIMITER + attrVal;
op = SearchParameters.Operator.CONTAINS;
break;
case ENDS_WITH:
attrVal = attrVal + CLASSIFICATION_NAME_DELIMITER;
op = SearchParameters.Operator.CONTAINS;
break;
case EQ:
attrVal = GraphHelper.getDelimitedClassificationNames(Collections.singleton(attrVal));
op = SearchParameters.Operator.CONTAINS;
break;
case NEQ:
attrVal = GraphHelper.getDelimitedClassificationNames(Collections.singleton(attrVal));
op = SearchParameters.Operator.NOT_CONTAINS;
break;
case CONTAINS:
if (attrName.equals(CUSTOM_ATTRIBUTES_PROPERTY_KEY)) {
attrVal = getCustomAttributeIndexQueryValue(attrVal, true);
}
break;
default:
LOG.warn("{}: unsupported operator. Ignored", op);
break;
}
}
ret.setAttributeName(attrName);
ret.setOperator(op);
ret.setAttributeValue(attrVal);
return ret;
}
private String toIndexExpression(AtlasStructType type, String attrName, SearchParameters.Operator op, String attrVal) {
String ret = EMPTY_STRING;
......@@ -499,7 +555,7 @@ public abstract class SearchProcessor {
// map '__customAttributes' 'CONTAINS' operator to 'EQ' operator (solr limitation for json serialized string search)
// map '__customAttributes' value from 'key1=value1' to '\"key1\":\"value1\"' (escape special characters and surround with quotes)
if (attrName.equals(CUSTOM_ATTRIBUTES_PROPERTY_KEY) && op == SearchParameters.Operator.CONTAINS) {
ret = String.format(OPERATOR_MAP.get(SearchParameters.Operator.EQ), qualifiedName, getCustomAttributeIndexQueryValue(escapeIndexQueryValue));
ret = String.format(OPERATOR_MAP.get(op), qualifiedName, getCustomAttributeIndexQueryValue(escapeIndexQueryValue, false));
} else {
ret = String.format(OPERATOR_MAP.get(op), qualifiedName, escapeIndexQueryValue);
}
......@@ -511,7 +567,7 @@ public abstract class SearchProcessor {
return ret;
}
private String getCustomAttributeIndexQueryValue(String attrValue) {
private String getCustomAttributeIndexQueryValue(String attrValue, boolean forGraphQuery) {
String ret = null;
if (StringUtils.isNotEmpty(attrValue)) {
......@@ -520,7 +576,11 @@ public abstract class SearchProcessor {
String value = key != null ? attrValue.substring(separatorIdx + 1) : null;
if (key != null && value != null) {
ret = String.format(CUSTOM_ATTR_SEARCH_FORMAT, key, value);
if (forGraphQuery) {
ret = String.format(CUSTOM_ATTR_SEARCH_FORMAT_GRAPH, key, value);
} else {
ret = String.format(CUSTOM_ATTR_SEARCH_FORMAT, key, value);
}
} else {
ret = attrValue;
}
......@@ -632,6 +692,13 @@ public abstract class SearchProcessor {
String attrValue = criteria.getAttributeValue();
SearchParameters.Operator operator = criteria.getOperator();
//process attribute value and attribute operator for pipeSeperated fields
if (isPipeSeparatedSystemAttribute(attrName)) {
FilterCriteria processedCriteria = processPipeSeperatedSystemAttribute(attrName, operator, attrValue);
attrValue = processedCriteria.getAttributeValue();
operator = processedCriteria.getOperator();
}
try {
final String qualifiedName = type.getQualifiedAttributeName(attrName);
......
......@@ -542,6 +542,43 @@ public class SearchPredicateUtil {
return ret;
}
public static VertexAttributePredicateGenerator getNotContainsPredicateGenerator() {
if (LOG.isDebugEnabled()) {
LOG.debug("==> getNotContainsPredicateGenerator");
}
VertexAttributePredicateGenerator ret = new VertexAttributePredicateGenerator() {
@Override
public Predicate generatePredicate(final String attrName, final Object attrVal, final Class attrClass) {
final Predicate ret;
if (attrName == null || attrClass == null || attrVal == null) {
ret = ALWAYS_FALSE;
} else if (String.class.isAssignableFrom(attrClass)) {
ret = StringPredicate.getNotContainsPredicate(attrName, attrClass, (String) attrVal);
} else if (Collection.class.isAssignableFrom(attrClass)) {
// Check if the provided value is present in the list of stored values
ret = new VertexAttributePredicate(attrName, attrClass) {
@Override
protected boolean compareValue(final Object vertexAttrVal) {
return !((Collection) vertexAttrVal).contains(attrVal);
}
};
} else {
ret = ALWAYS_FALSE;
}
return ret;
}
};
if (LOG.isDebugEnabled()) {
LOG.debug("<== getNotContainsPredicateGenerator");
}
return ret;
}
public static VertexAttributePredicateGenerator getIsNullPredicateGenerator() {
if (LOG.isDebugEnabled()) {
LOG.debug("==> getIsNullPredicateGenerator");
......@@ -1293,6 +1330,14 @@ public class SearchPredicateUtil {
};
}
static VertexAttributePredicate getNotContainsPredicate(String attrName, Class attrClass, String value) {
return new StringPredicate(attrName, attrClass, value) {
protected boolean compareValue(Object vertexAttrVal) {
return !((String) vertexAttrVal).contains(value);
}
};
}
static VertexAttributePredicate getStartsWithPredicate(String attrName, Class attrClass, String value) {
return new StringPredicate(attrName, attrClass, value) {
protected boolean compareValue(Object vertexAttrVal) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment