You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/09/13 19:33:02 UTC

atlas git commit: ATLAS-2115: Basic search updates to fix performance regression

Repository: atlas
Updated Branches:
  refs/heads/master 8348f2212 -> 1dc7f5499


ATLAS-2115: Basic search updates to fix performance regression

Signed-off-by: Madhan Neethiraj <ma...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/1dc7f549
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/1dc7f549
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/1dc7f549

Branch: refs/heads/master
Commit: 1dc7f54999952d18a677a3bc60f437071764cc16
Parents: 8348f22
Author: apoorvnaik <ap...@apache.org>
Authored: Fri Sep 8 09:19:06 2017 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Wed Sep 13 11:39:50 2017 -0700

----------------------------------------------------------------------
 .../atlas/model/discovery/SearchParameters.java |   4 +-
 .../ClassificationSearchProcessor.java          |  84 +++++++----
 .../atlas/discovery/EntitySearchProcessor.java  | 102 +++++++++-----
 .../apache/atlas/discovery/SearchProcessor.java |  50 ++++---
 .../apache/atlas/util/SearchPredicateUtil.java  | 138 +++++++++++++++++--
 5 files changed, 280 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/1dc7f549/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java b/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java
index 972c11e..c79b5b9 100644
--- a/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java
+++ b/intg/src/main/java/org/apache/atlas/model/discovery/SearchParameters.java
@@ -344,7 +344,9 @@ public class SearchParameters {
         LIKE(new String[]{"like", "LIKE"}),
         STARTS_WITH(new String[]{"startsWith", "STARTSWITH", "begins_with", "BEGINS_WITH"}),
         ENDS_WITH(new String[]{"endsWith", "ENDSWITH", "ends_with", "BEGINS_WITH"}),
-        CONTAINS(new String[]{"contains", "CONTAINS"})
+        CONTAINS(new String[]{"contains", "CONTAINS"}),
+        CONTAINS_ANY(new String[]{"containsAny", "CONTAINSANY", "contains_any", "CONTAINS_ANY"}),
+        CONTAINS_ALL(new String[]{"containsAll", "CONTAINSALL", "contains_all", "CONTAINS_ALL"})
         ;
         static final Map<String, Operator> operatorsMap = new HashMap<>();
 

http://git-wip-us.apache.org/repos/asf/atlas/blob/1dc7f549/repository/src/main/java/org/apache/atlas/discovery/ClassificationSearchProcessor.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/ClassificationSearchProcessor.java b/repository/src/main/java/org/apache/atlas/discovery/ClassificationSearchProcessor.java
index 0daab03..1d4815d 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/ClassificationSearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/ClassificationSearchProcessor.java
@@ -30,8 +30,10 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
 import org.apache.atlas.type.AtlasClassificationType;
 import org.apache.atlas.util.AtlasGremlinQueryProvider;
+import org.apache.atlas.util.SearchPredicateUtil;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.Predicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,11 +53,14 @@ public class ClassificationSearchProcessor extends SearchProcessor {
     private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("ClassificationSearchProcessor");
 
     private final AtlasIndexQuery indexQuery;
-    private final AtlasGraphQuery allGraphQuery;
+    private final AtlasGraphQuery tagGraphQueryWithAttributes;
+    private final AtlasGraphQuery entityGraphQueryTraitNames;
+    private final Predicate       entityPredicateTraitNames;
 
     private final String              gremlinTagFilterQuery;
     private final Map<String, Object> gremlinQueryBindings;
 
+
     public ClassificationSearchProcessor(SearchContext context) {
         super(context);
 
@@ -88,19 +93,19 @@ public class ClassificationSearchProcessor extends SearchProcessor {
 
             this.indexQuery = graph.indexQuery(Constants.VERTEX_INDEX, indexQueryString);
 
-            constructInMemoryPredicate(classificationType, filterCriteria, indexAttributes);
+            inMemoryPredicate = constructInMemoryPredicate(classificationType, filterCriteria, indexAttributes);
         } else {
             indexQuery = null;
         }
 
-        AtlasGraphQuery query = graph.query().in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes);
-
-        allGraphQuery = toGraphFilterQuery(classificationType, filterCriteria, allAttributes, query);
-
         if (context.getSearchParameters().getTagFilters() != null) {
             // Now filter on the tag attributes
             AtlasGremlinQueryProvider queryProvider = AtlasGremlinQueryProvider.INSTANCE;
 
+            tagGraphQueryWithAttributes = toGraphFilterQuery(classificationType, filterCriteria, allAttributes, graph.query().in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes));
+            entityGraphQueryTraitNames  = null;
+            entityPredicateTraitNames   = null;
+
             gremlinQueryBindings = new HashMap<>();
 
             StringBuilder gremlinQuery = new StringBuilder();
@@ -122,6 +127,11 @@ public class ClassificationSearchProcessor extends SearchProcessor {
                 LOG.debug("gremlinTagFilterQuery={}", gremlinTagFilterQuery);
             }
         } else {
+            tagGraphQueryWithAttributes = null;
+            entityGraphQueryTraitNames  = graph.query().in(Constants.TRAIT_NAMES_PROPERTY_KEY, typeAndSubTypes);
+            entityPredicateTraitNames   = SearchPredicateUtil.getContainsAnyPredicateGenerator()
+                                                             .generatePredicate(Constants.TRAIT_NAMES_PROPERTY_KEY, classificationType.getTypeAndAllSubTypes(), List.class);
+
             gremlinTagFilterQuery = null;
             gremlinQueryBindings  = null;
         }
@@ -176,38 +186,56 @@ public class ClassificationSearchProcessor extends SearchProcessor {
                     }
 
                     getVerticesFromIndexQueryResult(queryResult, classificationVertices);
+
+                    // Do in-memory filtering before the graph query
+                    CollectionUtils.filter(classificationVertices, inMemoryPredicate);
                 } else {
-                    Iterator<AtlasVertex> queryResult = allGraphQuery.vertices(qryOffset, limit).iterator();
+                    if (context.getSearchParameters().getTagFilters() == null) {
+                        // We can use single graph query to determine in this case
+                        Iterator<AtlasVertex> queryResult = entityGraphQueryTraitNames.vertices(qryOffset, limit).iterator();
 
-                    if (!queryResult.hasNext()) { // no more results - end of search
-                        break;
-                    }
+                        if (!queryResult.hasNext()) { // no more results - end of search
+                            break;
+                        }
 
-                    getVertices(queryResult, classificationVertices);
-                }
+                        getVertices(queryResult, entityVertices);
+                    } else {
+                        Iterator<AtlasVertex> queryResult = tagGraphQueryWithAttributes.vertices(qryOffset, limit).iterator();
 
-                // Do in-memory filtering before the graph query
-                CollectionUtils.filter(classificationVertices, inMemoryPredicate);
+                        if (!queryResult.hasNext()) { // no more results - end of search
+                            break;
+                        }
 
-                for (AtlasVertex classificationVertex : classificationVertices) {
-                    Iterable<AtlasEdge> edges = classificationVertex.getEdges(AtlasEdgeDirection.IN);
+                        getVertices(queryResult, classificationVertices);
 
-                    for (AtlasEdge edge : edges) {
-                        AtlasVertex entityVertex = edge.getOutVertex();
+                        // Do in-memory filtering before the graph query
+                        CollectionUtils.filter(classificationVertices, inMemoryPredicate);
+                    }
+                }
 
-                        if (activeOnly && AtlasGraphUtilsV1.getState(entityVertex) != AtlasEntity.Status.ACTIVE) {
-                            continue;
-                        }
+                // Since tag filters are present, we need to collect the entity vertices after filtering the classification
+                // vertex results (as these might be lower in number)
+                if (CollectionUtils.isNotEmpty(classificationVertices)) {
+                    for (AtlasVertex classificationVertex : classificationVertices) {
+                        Iterable<AtlasEdge> edges = classificationVertex.getEdges(AtlasEdgeDirection.IN);
 
-                        String guid = AtlasGraphUtilsV1.getIdFromVertex(entityVertex);
+                        for (AtlasEdge edge : edges) {
+                            AtlasVertex entityVertex = edge.getOutVertex();
 
-                        if (processedGuids.contains(guid)) {
-                            continue;
-                        }
+                            if (activeOnly && AtlasGraphUtilsV1.getState(entityVertex) != AtlasEntity.Status.ACTIVE) {
+                                continue;
+                            }
+
+                            String guid = AtlasGraphUtilsV1.getIdFromVertex(entityVertex);
 
-                        entityVertices.add(entityVertex);
+                            if (processedGuids.contains(guid)) {
+                                continue;
+                            }
 
-                        processedGuids.add(guid);
+                            entityVertices.add(entityVertex);
+
+                            processedGuids.add(guid);
+                        }
                     }
                 }
 
@@ -254,6 +282,8 @@ public class ClassificationSearchProcessor extends SearchProcessor {
                     LOG.warn(e.getMessage(), e);
                 }
             }
+        } else if (entityPredicateTraitNames != null) {
+            CollectionUtils.filter(entityVertices, entityPredicateTraitNames);
         }
 
         super.filter(entityVertices);

http://git-wip-us.apache.org/repos/asf/atlas/blob/1dc7f549/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java b/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
index a4a638a..970cd28 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
@@ -24,12 +24,16 @@ import org.apache.atlas.repository.graphdb.AtlasIndexQuery;
 import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.type.AtlasClassificationType;
 import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.util.SearchPredicateUtil;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.collections.PredicateUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -41,7 +45,8 @@ public class EntitySearchProcessor extends SearchProcessor {
 
     private final AtlasIndexQuery indexQuery;
     private final AtlasGraphQuery graphQuery;
-    private final AtlasGraphQuery filterGraphQuery;
+    private       Predicate       graphQueryPredicate;
+    private       Predicate       filterGraphQueryPredicate;
 
     public EntitySearchProcessor(SearchContext context) {
         super(context);
@@ -54,10 +59,18 @@ public class EntitySearchProcessor extends SearchProcessor {
         final Set<String>     graphAttributes       = new HashSet<>();
         final Set<String>     allAttributes         = new HashSet<>();
 
-        final AtlasClassificationType classificationType   = context.getClassificationType();
-        final boolean                 filterClassification = classificationType != null && !context.needClassificationProcessor();
+        final AtlasClassificationType classificationType            = context.getClassificationType();
+        final boolean                 filterClassification          = classificationType != null && !context.needClassificationProcessor();
+        final Set<String>             classificationTypeAndSubTypes = classificationType != null ? classificationType.getTypeAndAllSubTypes() : Collections.EMPTY_SET;
 
 
+        final Predicate typeNamePredicate = SearchPredicateUtil.getINPredicateGenerator()
+                                                               .generatePredicate(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes, String.class);
+        final Predicate traitPredicate    = SearchPredicateUtil.getContainsAnyPredicateGenerator()
+                                                               .generatePredicate(Constants.TRAIT_NAMES_PROPERTY_KEY, classificationTypeAndSubTypes, List.class);
+        final Predicate activePredicate   = SearchPredicateUtil.getEQPredicateGenerator()
+                                                               .generatePredicate(Constants.STATE_PROPERTY_KEY, "ACTIVE", String.class);
+
         processSearchAttributes(entityType, filterCriteria, indexAttributes, graphAttributes, allAttributes);
 
         final boolean typeSearchByIndex = !filterClassification && typeAndSubTypesQryStr.length() <= MAX_QUERY_STR_LENGTH_TYPES;
@@ -72,7 +85,7 @@ public class EntitySearchProcessor extends SearchProcessor {
         if (attrSearchByIndex) {
             constructFilterQuery(indexQuery, entityType, filterCriteria, indexAttributes);
 
-            constructInMemoryPredicate(entityType, filterCriteria, indexAttributes);
+            inMemoryPredicate = constructInMemoryPredicate(entityType, filterCriteria, indexAttributes);
         } else {
             graphAttributes.addAll(indexAttributes);
         }
@@ -97,31 +110,71 @@ public class EntitySearchProcessor extends SearchProcessor {
 
             if (!typeSearchByIndex) {
                 query.in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes);
+
+                // Construct a parallel in-memory predicate
+                if (graphQueryPredicate != null) {
+                    graphQueryPredicate = PredicateUtils.andPredicate(graphQueryPredicate, typeNamePredicate);
+                } else {
+                    graphQueryPredicate = typeNamePredicate;
+                }
             }
 
+            // If we need to filter on the trait names then we need to build the query and equivalent in-memory predicate
             if (filterClassification) {
-                query.in(Constants.TRAIT_NAMES_PROPERTY_KEY, classificationType.getTypeAndAllSubTypes());
+                query.in(Constants.TRAIT_NAMES_PROPERTY_KEY, classificationTypeAndSubTypes);
+
+                // Construct a parallel in-memory predicate
+                if (graphQueryPredicate != null) {
+                    graphQueryPredicate = PredicateUtils.andPredicate(graphQueryPredicate, traitPredicate);
+                } else {
+                    graphQueryPredicate = traitPredicate;
+                }
             }
 
             graphQuery = toGraphFilterQuery(entityType, filterCriteria, graphAttributes, query);
 
+            // Prepare in-memory predicate for attribute filtering
+            Predicate attributePredicate = constructInMemoryPredicate(entityType, filterCriteria, graphAttributes);
+
+            if (attributePredicate != null) {
+                if (graphQueryPredicate != null) {
+                    graphQueryPredicate = PredicateUtils.andPredicate(graphQueryPredicate, attributePredicate);
+                } else {
+                    graphQueryPredicate = attributePredicate;
+                }
+            }
+
+            // Filter condition for the STATUS
             if (context.getSearchParameters().getExcludeDeletedEntities() && this.indexQuery == null) {
                 graphQuery.has(Constants.STATE_PROPERTY_KEY, "ACTIVE");
+                if (graphQueryPredicate != null) {
+                    graphQueryPredicate = PredicateUtils.andPredicate(graphQueryPredicate, activePredicate);
+                } else {
+                    graphQueryPredicate = activePredicate;
+                }
             }
         } else {
             graphQuery = null;
+            graphQueryPredicate = null;
         }
 
-        AtlasGraphQuery query = context.getGraph().query().in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes);
 
-        if (filterClassification) {
-            query.in(Constants.TRAIT_NAMES_PROPERTY_KEY, classificationType.getTypeAndAllSubTypes());
+        // Prepare the graph query and in-memory filter for the filtering phase
+        filterGraphQueryPredicate = typeNamePredicate;
+
+        Predicate attributesPredicate = constructInMemoryPredicate(entityType, filterCriteria, allAttributes);
+
+        if (attributesPredicate != null) {
+            filterGraphQueryPredicate = PredicateUtils.andPredicate(filterGraphQueryPredicate, attributesPredicate);
         }
 
-        filterGraphQuery = toGraphFilterQuery(entityType, filterCriteria, allAttributes, query);
+        if (filterClassification) {
+            filterGraphQueryPredicate = PredicateUtils.andPredicate(filterGraphQueryPredicate, traitPredicate);
+        }
 
+        // Filter condition for the STATUS
         if (context.getSearchParameters().getExcludeDeletedEntities()) {
-            filterGraphQuery.has(Constants.STATE_PROPERTY_KEY, "ACTIVE");
+            filterGraphQueryPredicate = PredicateUtils.andPredicate(filterGraphQueryPredicate, activePredicate);
         }
     }
 
@@ -172,18 +225,8 @@ public class EntitySearchProcessor extends SearchProcessor {
                     // Do in-memory filtering before the graph query
                     CollectionUtils.filter(entityVertices, inMemoryPredicate);
 
-                    if (graphQuery != null) {
-                        Set<String> guids = getGuids(entityVertices);
-
-                        entityVertices.clear();
-
-                        if (CollectionUtils.isNotEmpty(guids)) {
-                            AtlasGraphQuery guidQuery = context.getGraph().query().in(Constants.GUID_PROPERTY_KEY, guids);
-
-                            guidQuery.addConditionsFrom(graphQuery);
-
-                            getVertices(guidQuery.vertices().iterator(), entityVertices);
-                        }
+                    if (graphQueryPredicate != null) {
+                        CollectionUtils.filter(entityVertices, graphQueryPredicate);
                     }
                 } else {
                     Iterator<AtlasVertex> queryResult = graphQuery.vertices(qryOffset, limit).iterator();
@@ -216,16 +259,11 @@ public class EntitySearchProcessor extends SearchProcessor {
             LOG.debug("==> EntitySearchProcessor.filter({})", entityVertices.size());
         }
 
-        Set<String> guids = getGuids(entityVertices);
-
-        entityVertices.clear();
-
-        if (CollectionUtils.isNotEmpty(guids)) {
-            AtlasGraphQuery query = context.getGraph().query().in(Constants.GUID_PROPERTY_KEY, guids);
-
-            query.addConditionsFrom(filterGraphQuery);
-
-            getVertices(query.vertices().iterator(), entityVertices);
+        // Since we already have the entity vertices, a in-memory filter will be faster than fetching the same
+        // vertices again with the required filtering
+        if (filterGraphQueryPredicate != null) {
+            LOG.debug("Filtering in-memory");
+            CollectionUtils.filter(entityVertices, filterGraphQueryPredicate);
         }
 
         super.filter(entityVertices);

http://git-wip-us.apache.org/repos/asf/atlas/blob/1dc7f549/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
index d5e3923..ddf117f 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
@@ -23,18 +23,20 @@ import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.discovery.SearchParameters;
 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.graphdb.AtlasGraphQuery;
 import org.apache.atlas.repository.graphdb.AtlasIndexQuery;
 import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
+import org.apache.atlas.type.AtlasArrayType;
 import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.type.AtlasEnumType;
 import org.apache.atlas.type.AtlasStructType;
 import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
 import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.util.AtlasGremlinQueryProvider;
-import org.apache.atlas.util.SearchPredicateUtil.VertexAttributePredicateGenerator;
+import org.apache.atlas.util.SearchPredicateUtil.*;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Predicate;
 import org.apache.commons.collections.PredicateUtils;
@@ -44,15 +46,7 @@ import org.slf4j.LoggerFactory;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 import java.util.regex.Pattern;
 
 import static org.apache.atlas.util.SearchPredicateUtil.*;
@@ -269,14 +263,16 @@ public abstract class SearchProcessor {
         }
     }
 
-    protected void constructInMemoryPredicate(AtlasStructType type, FilterCriteria filterCriteria, Set<String> indexAttributes) {
+    protected Predicate constructInMemoryPredicate(AtlasStructType type, FilterCriteria filterCriteria, Set<String> indexAttributes) {
+        Predicate ret = null;
         if (filterCriteria != null) {
             if (LOG.isDebugEnabled()) {
                 LOG.debug("Processing Filters");
             }
 
-            inMemoryPredicate = toInMemoryPredicate(type, filterCriteria, indexAttributes);
+            ret = toInMemoryPredicate(type, filterCriteria, indexAttributes);
         }
+        return ret;
     }
 
     protected void constructGremlinFilterQuery(StringBuilder gremlinQuery, Map<String, Object> queryBindings, AtlasStructType structType, FilterCriteria filterCriteria) {
@@ -411,59 +407,61 @@ public abstract class SearchProcessor {
         VertexAttributePredicateGenerator predicate = OPERATOR_PREDICATE_MAP.get(op);
 
         if (attribute != null && predicate != null) {
-            final AtlasType attrType      = attribute.getAttributeType();
-            final String    attributeType = attrType.getTypeName().toLowerCase();
+            final AtlasType attrType = attribute.getAttributeType();
             final Class     attrClass;
             final Object    attrValue;
 
-            switch (attributeType) {
-                case "string":
+            switch (attrType.getTypeName()) {
+                case AtlasBaseTypeDef.ATLAS_TYPE_STRING:
                     attrClass = String.class;
                     attrValue = attrVal;
                     break;
-                case "short":
+                case AtlasBaseTypeDef.ATLAS_TYPE_SHORT:
                     attrClass = Short.class;
                     attrValue = Short.parseShort(attrVal);
                     break;
-                case "int":
+                case AtlasBaseTypeDef.ATLAS_TYPE_INT:
                     attrClass = Integer.class;
                     attrValue = Integer.parseInt(attrVal);
                     break;
-                case "biginteger":
+                case AtlasBaseTypeDef.ATLAS_TYPE_BIGINTEGER:
                     attrClass = BigInteger.class;
                     attrValue = new BigInteger(attrVal);
                     break;
-                case "boolean":
+                case AtlasBaseTypeDef.ATLAS_TYPE_BOOLEAN:
                     attrClass = Boolean.class;
                     attrValue = Boolean.parseBoolean(attrVal);
                     break;
-                case "byte":
+                case AtlasBaseTypeDef.ATLAS_TYPE_BYTE:
                     attrClass = Byte.class;
                     attrValue = Byte.parseByte(attrVal);
                     break;
-                case "long":
-                case "date":
+                case AtlasBaseTypeDef.ATLAS_TYPE_LONG:
+                case AtlasBaseTypeDef.ATLAS_TYPE_DATE:
                     attrClass = Long.class;
                     attrValue = Long.parseLong(attrVal);
                     break;
-                case "float":
+                case AtlasBaseTypeDef.ATLAS_TYPE_FLOAT:
                     attrClass = Float.class;
                     attrValue = Float.parseFloat(attrVal);
                     break;
-                case "double":
+                case AtlasBaseTypeDef.ATLAS_TYPE_DOUBLE:
                     attrClass = Double.class;
                     attrValue = Double.parseDouble(attrVal);
                     break;
-                case "bigdecimal":
+                case AtlasBaseTypeDef.ATLAS_TYPE_BIGDECIMAL:
                     attrClass = BigDecimal.class;
                     attrValue = new BigDecimal(attrVal);
                     break;
                 default:
                     if (attrType instanceof AtlasEnumType) {
                         attrClass = String.class;
+                    } else if (attrType instanceof AtlasArrayType) {
+                        attrClass = List.class;
                     } else {
                         attrClass = Object.class;
                     }
+
                     attrValue = attrVal;
                     break;
             }

http://git-wip-us.apache.org/repos/asf/atlas/blob/1dc7f549/repository/src/main/java/org/apache/atlas/util/SearchPredicateUtil.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/util/SearchPredicateUtil.java b/repository/src/main/java/org/apache/atlas/util/SearchPredicateUtil.java
index fc973e6..18d77ee 100644
--- a/repository/src/main/java/org/apache/atlas/util/SearchPredicateUtil.java
+++ b/repository/src/main/java/org/apache/atlas/util/SearchPredicateUtil.java
@@ -19,13 +19,14 @@ package org.apache.atlas.util;
 
 import org.apache.atlas.repository.graphdb.AtlasVertex;
 import org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1;
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Predicate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.List;
+import java.util.Collection;
 
 public class SearchPredicateUtil {
     private static final Logger LOG = LoggerFactory.getLogger(SearchPredicateUtil.class);
@@ -228,6 +229,10 @@ public class SearchPredicateUtil {
 
                 if (attrName == null || attrClass == null || attrVal == null) {
                     ret = ALWAYS_FALSE;
+                } else if (Boolean.class.isAssignableFrom(attrClass)) {
+                    ret = BooleanPredicate.getEQPredicate(attrName, attrClass, (Boolean)attrVal);
+                } else if (Byte.class.isAssignableFrom(attrClass)) {
+                    ret = BytePredicate.getEQPredicate(attrName, attrClass, (Byte)attrVal);
                 } else if (Short.class.isAssignableFrom(attrClass)) {
                     ret = ShortPredicate.getEQPredicate(attrName, attrClass, (Short)attrVal);
                 } else if (Integer.class.isAssignableFrom(attrClass)) {
@@ -238,8 +243,6 @@ public class SearchPredicateUtil {
                     ret = FloatPredicate.getEQPredicate(attrName, attrClass, (Float)attrVal);
                 } else if (Double.class.isAssignableFrom(attrClass)) {
                     ret = DoublePredicate.getEQPredicate(attrName, attrClass, (Double)attrVal);
-                } else if (Byte.class.isAssignableFrom(attrClass)) {
-                    ret = BytePredicate.getEQPredicate(attrName, attrClass, (Byte)attrVal);
                 } else if (BigInteger.class.isAssignableFrom(attrClass)) {
                     ret = BigIntegerPredicate.getEQPredicate(attrName, attrClass, (BigInteger)attrVal);
                 } else if (BigDecimal.class.isAssignableFrom(attrClass)) {
@@ -273,6 +276,10 @@ public class SearchPredicateUtil {
 
                 if (attrName == null || attrClass == null || attrVal == null) {
                     ret = ALWAYS_FALSE;
+                } else if (Boolean.class.isAssignableFrom(attrClass)) {
+                    ret = BooleanPredicate.getNEQPredicate(attrName, attrClass, (Boolean)attrVal);
+                } else if (Byte.class.isAssignableFrom(attrClass)) {
+                    ret = BytePredicate.getNEQPredicate(attrName, attrClass, (Byte)attrVal);
                 } else if (Short.class.isAssignableFrom(attrClass)) {
                     ret = ShortPredicate.getNEQPredicate(attrName, attrClass, (Short)attrVal);
                 } else if (Integer.class.isAssignableFrom(attrClass)) {
@@ -283,8 +290,6 @@ public class SearchPredicateUtil {
                     ret = FloatPredicate.getNEQPredicate(attrName, attrClass, (Float)attrVal);
                 } else if (Double.class.isAssignableFrom(attrClass)) {
                     ret = DoublePredicate.getNEQPredicate(attrName, attrClass, (Double)attrVal);
-                } else if (Byte.class.isAssignableFrom(attrClass)) {
-                    ret = BytePredicate.getNEQPredicate(attrName, attrClass, (Byte)attrVal);
                 } else if (BigInteger.class.isAssignableFrom(attrClass)) {
                     ret = BigIntegerPredicate.getNEQPredicate(attrName, attrClass, (BigInteger)attrVal);
                 } else if (BigDecimal.class.isAssignableFrom(attrClass)) {
@@ -306,6 +311,76 @@ public class SearchPredicateUtil {
         return ret;
     }
 
+    public static VertexAttributePredicateGenerator getContainsAnyPredicateGenerator() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> getContainsAnyPredicateGenerator");
+        }
+
+        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 || !isValid(attrVal, attrClass)) {
+                    ret = ALWAYS_FALSE;
+                } else {
+                    ret = new VertexAttributePredicate(attrName, attrClass) {
+                        @Override
+                        public boolean compareValue(final Object value) {
+                            return CollectionUtils.containsAny((Collection) attrVal, (Collection) value);
+                        }
+                    };
+                }
+                return ret;
+            }
+
+            private boolean isValid(final Object attrVal, final Class attrClass) {
+                return attrVal instanceof Collection && Collection.class.isAssignableFrom(attrClass);
+            }
+        };
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== getContainsAnyPredicateGenerator");
+        }
+
+        return ret;
+    }
+
+    public static VertexAttributePredicateGenerator getContainsAllPredicateGenerator() {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> getContainsAllPredicateGenerator");
+        }
+
+        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 || !isValid(attrVal, attrClass)) {
+                    ret = ALWAYS_FALSE;
+                } else {
+                    ret = new VertexAttributePredicate(attrName, attrClass) {
+                        @Override
+                        public boolean compareValue(final Object value) {
+                            return ((Collection) attrVal).containsAll((Collection) value);
+                        }
+                    };
+                }
+                return ret;
+            }
+
+            private boolean isValid(final Object attrVal, final Class attrClass) {
+                return attrVal instanceof Collection && Collection.class.isAssignableFrom(attrClass);
+            }
+        };
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== getContainsAllPredicateGenerator");
+        }
+
+        return ret;
+    }
+
     public static VertexAttributePredicateGenerator getINPredicateGenerator() {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> getINPredicateGenerator");
@@ -316,19 +391,23 @@ public class SearchPredicateUtil {
             public Predicate generatePredicate(final String attrName, final Object attrVal, final Class attrClass) {
                 final Predicate ret;
 
-                if (attrName == null || attrClass == null || attrVal == null) {
+                if (attrName == null || attrClass == null || attrVal == null || !isValid(attrVal, attrClass)) {
                     ret = ALWAYS_FALSE;
                 } else {
                     ret = new VertexAttributePredicate(attrName, attrClass) {
                         @Override
                         public boolean compareValue(final Object value) {
-                            return (value instanceof List) ? ((List) value).contains(attrVal) : false;
+                            return ((Collection)attrVal).contains(value);
                         }
                     };
                 }
 
                 return ret;
             }
+
+            private boolean isValid(final Object attrVal, final Class attrClass) {
+                return attrVal instanceof Collection;
+            }
         };
 
         if (LOG.isDebugEnabled()) {
@@ -439,6 +518,14 @@ public class SearchPredicateUtil {
                     ret = ALWAYS_FALSE;
                 } else if (String.class.isAssignableFrom(attrClass)) {
                     ret = StringPredicate.getContainsPredicate(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 value) {
+                            return ((Collection) value).contains(attrVal);
+                        }
+                    };
                 } else {
                     ret = ALWAYS_FALSE;
                 }
@@ -474,13 +561,14 @@ public class SearchPredicateUtil {
             AtlasVertex vertex = (object instanceof AtlasVertex) ? (AtlasVertex)object : null;
 
             if (vertex != null) {
-                Object attrValue = AtlasGraphUtilsV1.getProperty(vertex, attrName, attrClass);
-
-                if (attrValue != null) {
-                    ret = compareValue(attrValue);
+                Object attrValue;
+                if (Collection.class.isAssignableFrom(attrClass)) {
+                    attrValue = vertex.getPropertyValues(attrName, attrClass);
                 } else {
-                    ret = false;
+                    attrValue = AtlasGraphUtilsV1.getProperty(vertex, attrName, attrClass);
                 }
+
+                ret = attrValue != null && compareValue(attrValue);
             } else {
                 ret = false;
             }
@@ -491,6 +579,32 @@ public class SearchPredicateUtil {
         protected abstract boolean compareValue(Object value);
     }
 
+    static abstract class BooleanPredicate extends VertexAttributePredicate {
+        final Boolean value;
+
+        BooleanPredicate(String attrName, Class attrClass, Boolean value) {
+            super(attrName, attrClass);
+
+            this.value = value;
+        }
+
+        static VertexAttributePredicate getEQPredicate(String attrName, Class attrClass, Boolean value) {
+            return new SearchPredicateUtil.BooleanPredicate(attrName, attrClass, value) {
+                protected boolean compareValue(Object value) {
+                    return ((Boolean) value).compareTo(this.value) == 0;
+                }
+            };
+        }
+
+        static VertexAttributePredicate getNEQPredicate(String attrName, Class attrClass, Boolean value) {
+            return new SearchPredicateUtil.BooleanPredicate(attrName, attrClass, value) {
+                protected boolean compareValue(Object value) {
+                    return ((Boolean) value).compareTo(this.value) != 0;
+                }
+            };
+        }
+    }
+
     static abstract class ShortPredicate extends VertexAttributePredicate {
         final Short value;