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 {