ATLAS-1961: Basic search improvement in use of Solr index for attribute filtering
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 605cb15..3204ecf 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/EntitySearchProcessor.java
@@ -20,7 +20,6 @@
 import org.apache.atlas.model.discovery.SearchParameters.FilterCriteria;
 import org.apache.atlas.repository.Constants;
 import org.apache.atlas.repository.graphdb.*;
-import org.apache.atlas.type.AtlasClassificationType;
 import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.utils.AtlasPerfTracer;
 import org.apache.commons.collections.CollectionUtils;
@@ -34,60 +33,70 @@
     private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("EntitySearchProcessor");
 
     private final AtlasIndexQuery indexQuery;
-    private final AtlasGraphQuery partialGraphQuery;
-    private final AtlasGraphQuery allGraphQuery;
+    private final AtlasGraphQuery graphQuery;
+    private final AtlasGraphQuery filterGraphQuery;
 
     public EntitySearchProcessor(SearchContext context) {
         super(context);
 
-        AtlasEntityType         entityType         = context.getEntityType();
-        AtlasClassificationType classificationType = context.getClassificationType();
-        FilterCriteria          filterCriteria     = context.getSearchParameters().getEntityFilters();
-        Set<String>             typeAndSubTypes    = entityType.getTypeAndAllSubTypes();
-        Set<String>             solrAttributes     = new HashSet<>();
-        Set<String>             gremlinAttributes  = new HashSet<>();
-        Set<String>             allAttributes      = new HashSet<>();
+        final AtlasEntityType entityType         = context.getEntityType();
+        final FilterCriteria  filterCriteria     = context.getSearchParameters().getEntityFilters();
+        final Set<String>     typeAndSubTypes    = entityType.getTypeAndAllSubTypes();
+        final Set<String>     solrAttributes     = new HashSet<>();
+        final Set<String>     gremlinAttributes  = new HashSet<>();
+        final Set<String>     allAttributes      = new HashSet<>();
 
 
         processSearchAttributes(entityType, filterCriteria, solrAttributes, gremlinAttributes, allAttributes);
 
-        boolean useSolrSearch = typeAndSubTypes.size() <= MAX_ENTITY_TYPES_IN_INDEX_QUERY && canApplySolrFilter(entityType, filterCriteria, false);
+        final boolean typeSearchBySolr = typeAndSubTypes.size() <= MAX_ENTITY_TYPES_IN_INDEX_QUERY;
+        final boolean attrSearchBySolr = canApplySolrFilter(entityType, filterCriteria, false);
 
-        if (useSolrSearch) {
-            StringBuilder solrQuery = new StringBuilder();
+        StringBuilder solrQuery = new StringBuilder();
 
+        if (typeSearchBySolr) {
             constructTypeTestQuery(solrQuery, typeAndSubTypes);
-            constructFilterQuery(solrQuery, entityType, filterCriteria, solrAttributes);
+        }
 
+        if (attrSearchBySolr) {
+            constructFilterQuery(solrQuery, entityType, filterCriteria, solrAttributes);
+        } else {
+            gremlinAttributes.addAll(solrAttributes);
+        }
+
+        if (solrQuery.length() > 0) {
             String solrQueryString = STRAY_AND_PATTERN.matcher(solrQuery).replaceAll(")");
 
             solrQueryString = STRAY_OR_PATTERN.matcher(solrQueryString).replaceAll(")");
             solrQueryString = STRAY_ELIPSIS_PATTERN.matcher(solrQueryString).replaceAll("");
 
             indexQuery = context.getGraph().indexQuery(Constants.VERTEX_INDEX, solrQueryString);
+        } else {
+            indexQuery = null;
+        }
 
-            if (CollectionUtils.isNotEmpty(gremlinAttributes) || classificationType != null) {
-                AtlasGraphQuery query = context.getGraph().query();
+        if (CollectionUtils.isNotEmpty(gremlinAttributes) || !typeSearchBySolr) {
+            AtlasGraphQuery query = context.getGraph().query();
 
-                addClassificationNameConditionIfNecessary(query);
+            if (!typeSearchBySolr) {
+                query.in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes);
+            }
 
-                partialGraphQuery = toGremlinFilterQuery(entityType, filterCriteria, gremlinAttributes, query);
-            } else {
-                partialGraphQuery = null;
+            graphQuery = toGremlinFilterQuery(entityType, filterCriteria, gremlinAttributes, query);
+
+            if (context.getSearchParameters().getExcludeDeletedEntities() && indexQuery == null) {
+                graphQuery.has(Constants.STATE_PROPERTY_KEY, "ACTIVE");
             }
         } else {
-            indexQuery      = null;
-            partialGraphQuery = null;
+            graphQuery = null;
         }
 
         AtlasGraphQuery query = context.getGraph().query().in(Constants.TYPE_NAME_PROPERTY_KEY, typeAndSubTypes);
 
-        addClassificationNameConditionIfNecessary(query);
-
-        allGraphQuery = toGremlinFilterQuery(entityType, filterCriteria, allAttributes, query);
+        filterGraphQuery = toGremlinFilterQuery(entityType, filterCriteria, allAttributes, query);
 
         if (context.getSearchParameters().getExcludeDeletedEntities()) {
-            allGraphQuery.has(Constants.STATE_PROPERTY_KEY, "ACTIVE");
+            filterGraphQuery.has(Constants.STATE_PROPERTY_KEY, "ACTIVE");
         }
     }
 
@@ -128,15 +137,15 @@
 
                     vertices = getVerticesFromIndexQueryResult(queryResult);
 
-                    if (partialGraphQuery != null) {
+                    if (graphQuery != null) {
                         AtlasGraphQuery guidQuery = context.getGraph().query().in(Constants.GUID_PROPERTY_KEY, getGuids(vertices));
 
-                        guidQuery.addConditionsFrom(partialGraphQuery);
+                        guidQuery.addConditionsFrom(graphQuery);
 
                         vertices = getVertices(guidQuery.vertices().iterator());
                     }
                 } else {
-                    Iterator<AtlasVertex> queryResult = allGraphQuery.vertices(qryOffset, limit).iterator();
+                    Iterator<AtlasVertex> queryResult = graphQuery.vertices(qryOffset, limit).iterator();
 
                     if (!queryResult.hasNext()) { // no more results from query - end of search
                         break;
@@ -182,7 +191,7 @@
 
         AtlasGraphQuery query = context.getGraph().query().in(Constants.GUID_PROPERTY_KEY, getGuids(entityVertices));
 
-        query.addConditionsFrom(allGraphQuery);
+        query.addConditionsFrom(filterGraphQuery);
 
         List<AtlasVertex> ret = getVertices(query.vertices().iterator());
 
@@ -194,10 +203,4 @@
 
         return ret;
     }
-
-    private void addClassificationNameConditionIfNecessary(AtlasGraphQuery query) {
-        if (context.getClassificationType() != null && !context.needClassificationProcessor()) {
-            query.in(Constants.TRAIT_NAMES_PROPERTY_KEY, context.getClassificationType().getTypeAndAllSubTypes());
-        }
-    }
 }
diff --git a/repository/src/main/java/org/apache/atlas/discovery/SearchContext.java b/repository/src/main/java/org/apache/atlas/discovery/SearchContext.java
index 55a07f3..8dd7667 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/SearchContext.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/SearchContext.java
@@ -109,7 +109,7 @@
     }
 
     public boolean needClassificationProcessor() {
-        return classificationType != null && (hasAttributeFilter(searchParameters.getTagFilters()) || entityType == null);
+        return classificationType != null;
     }
 
     public boolean needEntityProcessor() {
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 1481809..ff0bd2e 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
@@ -88,7 +88,7 @@
     public abstract List<AtlasVertex> execute();
 
     public List<AtlasVertex> filter(List<AtlasVertex> entityVertices) {
-        return nextProcessor == null ? entityVertices : nextProcessor.filter(entityVertices);
+        return nextProcessor == null || CollectionUtils.isEmpty(entityVertices) ? entityVertices : nextProcessor.filter(entityVertices);
     }
 
 
@@ -193,12 +193,20 @@
             String filterQuery = toSolrQuery(type, filterCriteria, solrAttributes, 0);
 
             if (StringUtils.isNotEmpty(filterQuery)) {
-                solrQuery.append(AND_STR).append(filterQuery);
+                if (solrQuery.length() > 0) {
+                    solrQuery.append(AND_STR);
+                }
+
+                solrQuery.append(filterQuery);
             }
         }
 
         if (type instanceof AtlasEntityType && context.getSearchParameters().getExcludeDeletedEntities()) {
-            solrQuery.append(AND_STR).append("v.\"__state\":").append("ACTIVE");
+            if (solrQuery.length() > 0) {
+                solrQuery.append(AND_STR);
+            }
+
+            solrQuery.append("v.\"__state\":").append("ACTIVE");
         }
     }