This is an automated email from the ASF dual-hosted git repository.

pinal-shah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new 5e90feeca ATLAS-5032: Updated CONTAINS so we only defer to JanusGraph 
when inde… (#672)
5e90feeca is described below

commit 5e90feeca6d57bc5fec695e21ec2042514241dcf
Author: saksenasonali <[email protected]>
AuthorDate: Thu Jun 18 10:40:43 2026 +0530

    ATLAS-5032: Updated CONTAINS so we only defer to JanusGraph when inde… 
(#672)
    
    * ATLAS-5032: Updated CONTAINS so we only defer to JanusGraph when 
indexType == null
    
    Co-authored-by: Cursor <[email protected]>
    
    ---------
    
    Co-authored-by: ssaksena <[email protected]>
    Co-authored-by: Cursor <[email protected]>
---
 .../apache/atlas/discovery/SearchProcessor.java    | 11 +--
 .../atlas/discovery/SearchProcessorTest.java       | 82 ++++++++++++++++++++++
 2 files changed, 88 insertions(+), 5 deletions(-)

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 9f7e3c3ab..3c3223d5c 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/SearchProcessor.java
@@ -869,15 +869,16 @@ public abstract class SearchProcessor {
 
                     ret = false;
                 } else if (operator == SearchParameters.Operator.CONTAINS) {
-                    if (StringUtils.length(attributeValue) > 
INDEX_SEARCH_MAX_TOKEN_STR_LENGTH
-                            || (indexType == null && 
AtlasAttribute.hastokenizeChar(attributeValue))) {
-                        LOG.debug("{} operator found for string attribute {} 
and filter value {}, deferring to in-memory or graph query (might cause poor 
performance)", operator, qualifiedName, attributeValue);
+                    // TEXT attributes (indexType == null) use Solr 
tokenization; STRING attributes (Mapping.STRING) do not
+                    if (indexType == null && 
(StringUtils.length(attributeValue) > INDEX_SEARCH_MAX_TOKEN_STR_LENGTH
+                            || 
AtlasAttribute.hastokenizeChar(attributeValue))) {
+                        LOG.debug("{} operator found for string (TEXT) 
attribute {} and filter value {}, deferring to in-memory or graph query (might 
cause poor performance)", operator, qualifiedName, attributeValue);
 
                         ret = false;
                     }
                 } else if ((operator == SearchParameters.Operator.STARTS_WITH 
|| operator == SearchParameters.Operator.ENDS_WITH)
-                        && StringUtils.length(attributeValue) > 
INDEX_SEARCH_MAX_TOKEN_STR_LENGTH) {
-                    LOG.debug("{} operator found for string attribute {} (max 
token length:{}) and filter value {}, deferring to in-memory or graph query 
(might cause poor performance)", operator, qualifiedName, 
INDEX_SEARCH_MAX_TOKEN_STR_LENGTH, attributeValue);
+                        && indexType == null && 
StringUtils.length(attributeValue) > INDEX_SEARCH_MAX_TOKEN_STR_LENGTH) {
+                    LOG.debug("{} operator found for string (TEXT) attribute 
{} (max token length:{}) and filter value {}, deferring to in-memory or graph 
query (might cause poor performance)", operator, qualifiedName, 
INDEX_SEARCH_MAX_TOKEN_STR_LENGTH, attributeValue);
 
                     ret = false;
                 }
diff --git 
a/repository/src/test/java/org/apache/atlas/discovery/SearchProcessorTest.java 
b/repository/src/test/java/org/apache/atlas/discovery/SearchProcessorTest.java
index c1a9991b5..3c519656e 100644
--- 
a/repository/src/test/java/org/apache/atlas/discovery/SearchProcessorTest.java
+++ 
b/repository/src/test/java/org/apache/atlas/discovery/SearchProcessorTest.java
@@ -23,6 +23,8 @@ 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.discovery.SearchParameters.Operator;
+import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
 import org.apache.atlas.repository.Constants;
 import org.apache.atlas.repository.graphdb.AtlasEdge;
 import org.apache.atlas.repository.graphdb.AtlasGraph;
@@ -32,7 +34,9 @@ import 
org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2;
 import org.apache.atlas.type.AtlasClassificationType;
 import org.apache.atlas.type.AtlasEntityType;
 import org.apache.atlas.type.AtlasRelationshipType;
+import org.apache.atlas.type.AtlasStructType;
 import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
+import org.apache.atlas.type.AtlasType;
 import org.apache.atlas.type.AtlasTypeRegistry;
 import org.apache.commons.collections.Predicate;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
@@ -47,6 +51,7 @@ import org.testng.annotations.Test;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -535,6 +540,83 @@ public class SearchProcessorTest {
         }
     }
 
+    private static final String LONG_FILTER_VALUE;
+
+    static {
+        char[] chars = new char[300];
+        Arrays.fill(chars, 'x');
+        LONG_FILTER_VALUE = new String(chars);
+    }
+
+    @Test
+    public void testContainsLongValueTextIndexTypeNotIndexSearchable() throws 
Exception {
+        assertFalse(isIndexSearchableForAttribute("qualifiedName", 
"qualifiedName", Operator.CONTAINS,
+                LONG_FILTER_VALUE, null));
+    }
+
+    @Test
+    public void testContainsLongValueStringIndexTypeIsIndexSearchable() throws 
Exception {
+        assertTrue(isIndexSearchableForAttribute("owner", "__s_owner", 
Operator.CONTAINS,
+                LONG_FILTER_VALUE, 
AtlasStructDef.AtlasAttributeDef.IndexType.STRING));
+    }
+
+    @Test
+    public void testContainsShortValueTextIndexTypeIsIndexSearchable() throws 
Exception {
+        assertTrue(isIndexSearchableForAttribute("qualifiedName", 
"qualifiedName", Operator.CONTAINS,
+                "default.table", null));
+    }
+
+    @Test
+    public void testStartsWithLongValueTextIndexTypeNotIndexSearchable() 
throws Exception {
+        assertFalse(isIndexSearchableForAttribute("qualifiedName", 
"qualifiedName", Operator.STARTS_WITH,
+                LONG_FILTER_VALUE, null));
+    }
+
+    @Test
+    public void testStartsWithLongValueStringIndexTypeIsIndexSearchable() 
throws Exception {
+        assertTrue(isIndexSearchableForAttribute("owner", "__s_owner", 
Operator.STARTS_WITH,
+                LONG_FILTER_VALUE, 
AtlasStructDef.AtlasAttributeDef.IndexType.STRING));
+    }
+
+    @Test
+    public void testEndsWithLongValueTextIndexTypeNotIndexSearchable() throws 
Exception {
+        assertFalse(isIndexSearchableForAttribute("qualifiedName", 
"qualifiedName", Operator.ENDS_WITH,
+                LONG_FILTER_VALUE, null));
+    }
+
+    @Test
+    public void testEndsWithLongValueStringIndexTypeIsIndexSearchable() throws 
Exception {
+        assertTrue(isIndexSearchableForAttribute("owner", "__s_owner", 
Operator.ENDS_WITH,
+                LONG_FILTER_VALUE, 
AtlasStructDef.AtlasAttributeDef.IndexType.STRING));
+    }
+
+    private boolean isIndexSearchableForAttribute(String attributeName, String 
vertexPropertyName,
+                                                 Operator operator, String 
attributeValue,
+                                                 
AtlasStructDef.AtlasAttributeDef.IndexType indexType) throws Exception {
+        FilterCriteria filterCriteria = new FilterCriteria();
+        filterCriteria.setAttributeName(attributeName);
+        filterCriteria.setOperator(operator);
+        filterCriteria.setAttributeValue(attributeValue);
+
+        AtlasStructType structType = mock(AtlasStructType.class);
+        AtlasType         attrType = mock(AtlasType.class);
+        AtlasStructDef.AtlasAttributeDef attributeDef = 
mock(AtlasStructDef.AtlasAttributeDef.class);
+
+        when(structType.getAttributeType(attributeName)).thenReturn(attrType);
+        
when(attrType.getTypeName()).thenReturn(AtlasBaseTypeDef.ATLAS_TYPE_STRING);
+        
when(structType.getVertexPropertyName(attributeName)).thenReturn(vertexPropertyName);
+        
when(structType.getAttributeDef(attributeName)).thenReturn(attributeDef);
+        when(attributeDef.getIndexType()).thenReturn(indexType);
+
+        Set<String> indexedKeys = new 
HashSet<>(Collections.singletonList(vertexPropertyName));
+        when(context.getIndexedKeys()).thenReturn(indexedKeys);
+        when(context.getEdgeIndexKeys()).thenReturn(Collections.emptySet());
+
+        Method method = 
SearchProcessor.class.getDeclaredMethod("isIndexSearchable", 
FilterCriteria.class, AtlasStructType.class);
+        method.setAccessible(true);
+        return (Boolean) method.invoke(searchProcessor, filterCriteria, 
structType);
+    }
+
     @Test
     public void testSearchProcessorUtilityMethods() throws Exception {
         try {

Reply via email to