This is an automated email from the ASF dual-hosted git repository. sarath pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/branch-2.0 by this push: new 1a2ca74 ATLAS-4403: Improve find entity by unique attributes logic - when multiple unique attributes exist for entity type 1a2ca74 is described below commit 1a2ca741115c7957c994e562f6a0fb2bc75da8dd Author: Sarath Subramanian <sar...@apache.org> AuthorDate: Fri Aug 27 14:11:52 2021 -0700 ATLAS-4403: Improve find entity by unique attributes logic - when multiple unique attributes exist for entity type (cherry picked from commit 097f50eae35e927411af3593fa401a335e61a0e3) --- .../store/graph/v2/AtlasGraphUtilsV2.java | 201 ++++++++------------- 1 file changed, 80 insertions(+), 121 deletions(-) diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java index e73f084..2fce123 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java @@ -59,6 +59,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -70,6 +71,7 @@ import static org.apache.atlas.repository.Constants.INDEX_SEARCH_VERTEX_PREFIX_D import static org.apache.atlas.repository.Constants.INDEX_SEARCH_VERTEX_PREFIX_PROPERTY; import static org.apache.atlas.repository.Constants.PROPAGATED_CLASSIFICATION_NAMES_KEY; import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY; +import static org.apache.atlas.repository.Constants.SUPER_TYPES_PROPERTY_KEY; import static org.apache.atlas.repository.Constants.TYPENAME_PROPERTY_KEY; import static org.apache.atlas.repository.Constants.TYPE_NAME_PROPERTY_KEY; import static org.apache.atlas.repository.graph.AtlasGraphProvider.getGraphInstance; @@ -316,48 +318,29 @@ public class AtlasGraphUtilsV2 { } public static AtlasVertex findByUniqueAttributes(AtlasGraph graph, AtlasEntityType entityType, Map<String, Object> attrValues) { - MetricRecorder metric = RequestContext.get().startMetricRecord("findByUniqueAttributes"); - - AtlasVertex vertex = null; - + MetricRecorder metric = RequestContext.get().startMetricRecord("findByUniqueAttributes"); + AtlasVertex vertex = null; final Map<String, AtlasAttribute> uniqueAttributes = entityType.getUniqAttributes(); if (MapUtils.isNotEmpty(uniqueAttributes) && MapUtils.isNotEmpty(attrValues)) { - for (AtlasAttribute attribute : uniqueAttributes.values()) { - Object attrValue = attrValues.get(attribute.getName()); + Map<String, Object> uniqAttrValues = populateUniqueAttributesMap(uniqueAttributes, attrValues); + Map<String, Object> attrNameValues = populateAttributesMap(uniqueAttributes, attrValues); + String typeName = entityType.getTypeName(); + Set<String> entitySubTypes = entityType.getAllSubTypes(); - if (attrValue == null) { - continue; - } - - if (canUseIndexQuery(graph, entityType, attribute.getName())) { - vertex = AtlasGraphUtilsV2.getAtlasVertexFromIndexQuery(graph, entityType, attribute, attrValue); - } else { - if (USE_UNIQUE_INDEX_PROPERTY_TO_FIND_ENTITY && attribute.getVertexUniquePropertyName() != null) { - vertex = AtlasGraphUtilsV2.findByTypeAndUniquePropertyName(graph, entityType.getTypeName(), attribute.getVertexUniquePropertyName(), attrValue); - - // if no instance of given typeName is found, try to find an instance of type's sub-type - if (vertex == null && !entityType.getAllSubTypes().isEmpty()) { - vertex = AtlasGraphUtilsV2.findBySuperTypeAndUniquePropertyName(graph, entityType.getTypeName(), attribute.getVertexUniquePropertyName(), attrValue); - } - } else { - vertex = AtlasGraphUtilsV2.findByTypeAndPropertyName(graph, entityType.getTypeName(), attribute.getVertexPropertyName(), attrValue); - - // if no instance of given typeName is found, try to find an instance of type's sub-type - if (vertex == null && !entityType.getAllSubTypes().isEmpty()) { - vertex = AtlasGraphUtilsV2.findBySuperTypeAndPropertyName(graph, entityType.getTypeName(), attribute.getVertexPropertyName(), attrValue); - } - } + if (USE_UNIQUE_INDEX_PROPERTY_TO_FIND_ENTITY && MapUtils.isNotEmpty(uniqAttrValues)) { + vertex = findByTypeAndUniquePropertyName(graph, typeName, uniqAttrValues); + // if no instance of given typeName is found, try to find an instance of type's sub-type + if (vertex == null && !entitySubTypes.isEmpty()) { + vertex = findBySuperTypeAndUniquePropertyName(graph, typeName, uniqAttrValues); } + } else { + vertex = findByTypeAndPropertyName(graph, typeName, attrNameValues); - if (vertex != null) { - if (LOG.isDebugEnabled()) { - LOG.debug("findByUniqueAttributes(type={}, attrName={}, attrValue={}: found vertex {}", - entityType.getTypeName(), attribute.getName(), attrValue, vertex); - } - - break; + // if no instance of given typeName is found, try to find an instance of type's sub-type + if (vertex == null && !entitySubTypes.isEmpty()) { + vertex = findBySuperTypeAndPropertyName(graph, typeName, attrNameValues); } } } @@ -484,50 +467,87 @@ public class AtlasGraphUtilsV2 { return vertex; } - public static AtlasVertex findBySuperTypeAndUniquePropertyName(AtlasGraph graph, String typeName, String propertyName, Object attrVal) { - MetricRecorder metric = RequestContext.get().startMetricRecord("findBySuperTypeAndUniquePropertyName"); + private static Map<String, Object> populateUniqueAttributesMap(Map<String, AtlasAttribute> uniqueAttributes, Map<String, Object> attrValues) { + return populateAttributesMap(uniqueAttributes, attrValues, true); + } - AtlasGraphQuery query = graph.query() - .has(Constants.SUPER_TYPES_PROPERTY_KEY, typeName) - .has(propertyName, attrVal); + private static Map<String, Object> populateAttributesMap(Map<String, AtlasAttribute> uniqueAttributes, Map<String, Object> attrValues) { + return populateAttributesMap(uniqueAttributes, attrValues, false); + } - Iterator<AtlasVertex> results = query.vertices().iterator(); + private static Map<String, Object> populateAttributesMap(Map<String, AtlasAttribute> uniqueAttributes, Map<String, Object> attrValues, boolean isUnique) { + Map<String, Object> ret = new HashMap<>(); - AtlasVertex vertex = results.hasNext() ? results.next() : null; + for (AtlasAttribute attribute : uniqueAttributes.values()) { + String attrName = isUnique ? attribute.getVertexUniquePropertyName() : attribute.getVertexPropertyName(); + Object attrValue = attrValues.get(attribute.getName()); - RequestContext.get().endMetricRecord(metric); + if (attrName != null && attrValue != null) { + ret.put(attrName, attrValue); + } + } - return vertex; + return ret; } - public static AtlasVertex findByTypeAndPropertyName(AtlasGraph graph, String typeName, String propertyName, Object attrVal) { - MetricRecorder metric = RequestContext.get().startMetricRecord("findByTypeAndPropertyName"); + public static AtlasVertex findByTypeAndUniquePropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues) { + return findByTypeAndUniquePropertyName(graph, typeName, attributeValues, false); + } - AtlasGraphQuery query = graph.query() - .has(ENTITY_TYPE_PROPERTY_KEY, typeName) - .has(propertyName, attrVal) - .has(STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE.name()); + public static AtlasVertex findBySuperTypeAndUniquePropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues) { + return findByTypeAndUniquePropertyName(graph, typeName, attributeValues, true); + } - Iterator<AtlasVertex> results = query.vertices().iterator(); + public static AtlasVertex findByTypeAndUniquePropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues, boolean isSuperType) { + String metricName = isSuperType ? "findBySuperTypeAndUniquePropertyName" : "findByTypeAndUniquePropertyName"; + MetricRecorder metric = RequestContext.get().startMetricRecord(metricName); + String typePropertyKey = isSuperType ? SUPER_TYPES_PROPERTY_KEY : ENTITY_TYPE_PROPERTY_KEY; + AtlasGraphQuery query = graph.query().has(typePropertyKey, typeName); - AtlasVertex vertex = results.hasNext() ? results.next() : null; + for (Map.Entry<String, Object> entry : attributeValues.entrySet()) { + String attrName = entry.getKey(); + Object attrValue = entry.getValue(); + + if (attrName != null && attrValue != null) { + query.has(attrName, attrValue); + } + } + + Iterator<AtlasVertex> results = query.vertices().iterator(); + AtlasVertex vertex = results.hasNext() ? results.next() : null; RequestContext.get().endMetricRecord(metric); return vertex; } - public static AtlasVertex findBySuperTypeAndPropertyName(AtlasGraph graph, String typeName, String propertyName, Object attrVal) { - MetricRecorder metric = RequestContext.get().startMetricRecord("findBySuperTypeAndPropertyName"); + public static AtlasVertex findByTypeAndPropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues) { + return findByTypeAndPropertyName(graph, typeName, attributeValues, false); + } - AtlasGraphQuery query = graph.query() - .has(Constants.SUPER_TYPES_PROPERTY_KEY, typeName) - .has(propertyName, attrVal) - .has(STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE.name()); + public static AtlasVertex findBySuperTypeAndPropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues) { + return findByTypeAndPropertyName(graph, typeName, attributeValues, true); + } - Iterator<AtlasVertex> results = query.vertices().iterator(); + public static AtlasVertex findByTypeAndPropertyName(AtlasGraph graph, String typeName, Map<String, Object> attributeValues, boolean isSuperType) { + String metricName = isSuperType ? "findBySuperTypeAndPropertyName" : "findByTypeAndPropertyName"; + MetricRecorder metric = RequestContext.get().startMetricRecord(metricName); + String typePropertyKey = isSuperType ? SUPER_TYPES_PROPERTY_KEY : ENTITY_TYPE_PROPERTY_KEY; + AtlasGraphQuery query = graph.query() + .has(typePropertyKey, typeName) + .has(STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE.name()); - AtlasVertex vertex = results.hasNext() ? results.next() : null; + for (Map.Entry<String, Object> entry : attributeValues.entrySet()) { + String attrName = entry.getKey(); + Object attrValue = entry.getValue(); + + if (attrName != null && attrValue != null) { + query.has(attrName, attrValue); + } + } + + Iterator<AtlasVertex> results = query.vertices().iterator(); + AtlasVertex vertex = results.hasNext() ? results.next() : null; RequestContext.get().endMetricRecord(metric); @@ -646,67 +666,6 @@ public class AtlasGraphUtilsV2 { return element.getProperty(STATE_PROPERTY_KEY, String.class); } - private static boolean canUseIndexQuery(AtlasGraph graph, AtlasEntityType entityType, String attributeName) { - boolean ret = false; - - if (USE_INDEX_QUERY_TO_FIND_ENTITY_BY_UNIQUE_ATTRIBUTES) { - final String typeAndSubTypesQryStr = entityType.getTypeAndAllSubTypesQryStr(); - - ret = typeAndSubTypesQryStr.length() <= SearchProcessor.MAX_QUERY_STR_LENGTH_TYPES; - - if (ret) { - Set<String> indexSet = graph.getVertexIndexKeys(); - try { - ret = indexSet.contains(entityType.getVertexPropertyName(attributeName)); - } - catch (AtlasBaseException ex) { - ret = false; - } - } - } - - return ret; - } - - private static AtlasVertex getAtlasVertexFromIndexQuery(AtlasGraph graph, AtlasEntityType entityType, AtlasAttribute attribute, Object attrVal) { - String propertyName = attribute.getVertexPropertyName(); - AtlasIndexQuery query = getIndexQuery(graph, entityType, propertyName, attrVal.toString()); - - for (Iterator<Result> iter = query.vertices(); iter.hasNext(); ) { - Result result = iter.next(); - AtlasVertex vertex = result.getVertex(); - - // skip non-entity vertices, if any got returned - if (vertex == null || !vertex.getPropertyKeys().contains(Constants.GUID_PROPERTY_KEY)) { - continue; - } - - // verify the typeName - String typeNameInVertex = getTypeName(vertex); - - if (!entityType.getTypeAndAllSubTypes().contains(typeNameInVertex)) { - LOG.warn("incorrect vertex type from index-query: expected='{}'; found='{}'", entityType.getTypeName(), typeNameInVertex); - - continue; - } - - if (attrVal.getClass() == String.class) { - String s = (String) attrVal; - String vertexVal = vertex.getProperty(propertyName, String.class); - - if (!s.equalsIgnoreCase(vertexVal)) { - LOG.warn("incorrect match from index-query for property {}: expected='{}'; found='{}'", propertyName, s, vertexVal); - - continue; - } - } - - return vertex; - } - - return null; - } - private static AtlasIndexQuery getIndexQuery(AtlasGraph graph, AtlasEntityType entityType, String propertyName, String value) { StringBuilder sb = new StringBuilder();