ATLAS-4671: Basic Search : Exclude Header attributes of entities from the response
Signed-off-by: Pinal Shah <pinal.shah@freestoneinfotech.com>
This commit is contained in:
parent
e3a6d238e3
commit
37c242755c
|
|
@ -50,6 +50,7 @@ public class QuickSearchParameters implements Serializable {
|
|||
private Set<String> attributes;
|
||||
private String sortBy;
|
||||
private SortOrder sortOrder;
|
||||
private boolean excludeHeaderAttributes;
|
||||
|
||||
/**
|
||||
* for framework use.
|
||||
|
|
@ -158,4 +159,12 @@ public class QuickSearchParameters implements Serializable {
|
|||
public void setSortOrder(SortOrder sortOrder) {
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public boolean getExcludeHeaderAttributes() {
|
||||
return excludeHeaderAttributes;
|
||||
}
|
||||
|
||||
public void setExcludeHeaderAttributes(boolean excludeHeaderAttributes) {
|
||||
this.excludeHeaderAttributes = excludeHeaderAttributes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public class SearchParameters implements Serializable {
|
|||
private boolean includeClassificationAttributes;
|
||||
private boolean includeSubTypes = true;
|
||||
private boolean includeSubClassifications = true;
|
||||
private boolean excludeHeaderAttributes = false;
|
||||
|
||||
private int limit;
|
||||
private int offset;
|
||||
private String marker;
|
||||
|
|
@ -258,6 +260,14 @@ public class SearchParameters implements Serializable {
|
|||
this.tagFilters = tagFilters;
|
||||
}
|
||||
|
||||
public boolean getExcludeHeaderAttributes() {
|
||||
return excludeHeaderAttributes;
|
||||
}
|
||||
|
||||
public void setExcludeHeaderAttributes(boolean excludeHeaderAttributes) {
|
||||
this.excludeHeaderAttributes = excludeHeaderAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute values included in the results
|
||||
* @return
|
||||
|
|
@ -307,6 +317,7 @@ public class SearchParameters implements Serializable {
|
|||
includeClassificationAttributes == that.includeClassificationAttributes &&
|
||||
includeSubTypes == that.includeSubTypes &&
|
||||
includeSubClassifications == that.includeSubClassifications &&
|
||||
excludeHeaderAttributes == that.excludeHeaderAttributes &&
|
||||
limit == that.limit &&
|
||||
offset == that.offset &&
|
||||
Objects.equals(query, that.query) &&
|
||||
|
|
@ -323,7 +334,7 @@ public class SearchParameters implements Serializable {
|
|||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(query, typeName, classification, termName, includeSubTypes, includeSubClassifications,
|
||||
excludeDeletedEntities, includeClassificationAttributes, limit, offset, entityFilters,
|
||||
excludeDeletedEntities, includeClassificationAttributes, excludeHeaderAttributes, limit, offset, entityFilters,
|
||||
tagFilters, attributes, sortBy, sortOrder);
|
||||
}
|
||||
|
||||
|
|
@ -341,6 +352,7 @@ public class SearchParameters implements Serializable {
|
|||
sb.append(", includeSubClassifications='").append(includeSubClassifications).append('\'');
|
||||
sb.append(", excludeDeletedEntities=").append(excludeDeletedEntities);
|
||||
sb.append(", includeClassificationAttributes=").append(includeClassificationAttributes);
|
||||
sb.append(", excludeHeaderAttributes=").append(excludeHeaderAttributes);
|
||||
sb.append(", limit=").append(limit);
|
||||
sb.append(", offset=").append(offset);
|
||||
sb.append(", entityFilters=").append(entityFilters);
|
||||
|
|
|
|||
|
|
@ -468,6 +468,32 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
|
|||
ret.setNextMarker(nextMarker);
|
||||
}
|
||||
|
||||
//If excludeHeaderAttributes is true, only primitive attributes requested in 'attributes' field will be sent in the response
|
||||
Set<String> attributes = searchParameters.getAttributes();
|
||||
if (searchContext.excludeHeaderAttributes()) {
|
||||
|
||||
AtlasSearchResult.AttributeSearchResult attributeSearchResult = new AtlasSearchResult.AttributeSearchResult();
|
||||
attributeSearchResult.setName(new ArrayList<>(attributes));
|
||||
|
||||
Collection<List<Object>> values = new ArrayList<>();
|
||||
for (AtlasVertex vertex : resultList) {
|
||||
List<Object> row = new ArrayList<>();
|
||||
|
||||
for (String attrName : attributes) {
|
||||
AtlasEntityType entityType = searchContext.getEntityTypes().iterator().next();
|
||||
AtlasAttribute attribute = entityType.getAttribute(attrName);
|
||||
Object value = vertex.getProperty(attribute.getVertexPropertyName(), Object.class);
|
||||
|
||||
row.add(value != null ? value : StringUtils.EMPTY);
|
||||
}
|
||||
values.add(row);
|
||||
}
|
||||
attributeSearchResult.setValues(new ArrayList<>(values));
|
||||
|
||||
ret.setAttributes(attributeSearchResult);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// By default any attribute that shows up in the search parameter should be sent back in the response
|
||||
// If additional values are requested then the entityAttributes will be a superset of the all search attributes
|
||||
// and the explicitly requested attribute(s)
|
||||
|
|
@ -922,6 +948,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
|
|||
searchParameters.setAttributes(quickSearchParameters.getAttributes());
|
||||
searchParameters.setSortBy(quickSearchParameters.getSortBy());
|
||||
searchParameters.setSortOrder(quickSearchParameters.getSortOrder());
|
||||
searchParameters.setExcludeHeaderAttributes(quickSearchParameters.getExcludeHeaderAttributes());
|
||||
|
||||
return searchParameters;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,10 +32,13 @@ import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
|
|||
import org.apache.atlas.repository.graphdb.AtlasVertex;
|
||||
import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2;
|
||||
import org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever;
|
||||
import org.apache.atlas.type.AtlasArrayType;
|
||||
import org.apache.atlas.type.AtlasBuiltInTypes;
|
||||
import org.apache.atlas.type.AtlasClassificationType;
|
||||
import org.apache.atlas.type.AtlasEntityType;
|
||||
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.atlas.util.AtlasRepositoryConfiguration;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
|
@ -86,6 +89,7 @@ public class SearchContext {
|
|||
private boolean terminateSearch = false;
|
||||
private SearchProcessor searchProcessor;
|
||||
private Integer marker;
|
||||
private boolean hasRelationshipAttributes = false;
|
||||
|
||||
public final static AtlasClassificationType MATCH_ALL_WILDCARD_CLASSIFICATION = new AtlasClassificationType(new AtlasClassificationDef(WILDCARD_CLASSIFICATIONS));
|
||||
public final static AtlasClassificationType MATCH_ALL_CLASSIFIED = new AtlasClassificationType(new AtlasClassificationDef(ALL_CLASSIFICATIONS));
|
||||
|
|
@ -146,6 +150,9 @@ public class SearchContext {
|
|||
//remove other types if builtin type is present
|
||||
filterStructTypes();
|
||||
|
||||
//validate 'attributes' field
|
||||
validateAttributes();
|
||||
|
||||
//gather all classifications and its corresponding subtypes
|
||||
Set<String> classificationTypeAndSubTypes = new HashSet<>();
|
||||
String classificationTypeAndSubTypesQryStr = null;
|
||||
|
|
@ -345,6 +352,37 @@ public class SearchContext {
|
|||
}
|
||||
}
|
||||
|
||||
private void validateAttributes() throws AtlasBaseException {
|
||||
Set<String> attributes = searchParameters.getAttributes();
|
||||
if (CollectionUtils.isNotEmpty(attributes) && CollectionUtils.isNotEmpty(entityTypes)) {
|
||||
|
||||
AtlasEntityType entityType = entityTypes.iterator().next();
|
||||
for (String attr : attributes) {
|
||||
AtlasAttribute attribute = entityType.getAttribute(attr);
|
||||
|
||||
if (attribute == null) {
|
||||
attribute = entityType.getRelationshipAttribute(attr, null);
|
||||
hasRelationshipAttributes = attribute != null;
|
||||
}
|
||||
|
||||
if (attribute == null) {
|
||||
throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attr, entityType.getTypeName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean excludeHeaderAttributes() {
|
||||
if (CollectionUtils.isNotEmpty(entityTypes) &&
|
||||
searchParameters.getExcludeHeaderAttributes() &&
|
||||
CollectionUtils.isNotEmpty(searchParameters.getAttributes()) &&
|
||||
!hasRelationshipAttributes){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasAttributeFilter(FilterCriteria filterCriteria) {
|
||||
return filterCriteria != null &&
|
||||
(CollectionUtils.isNotEmpty(filterCriteria.getCriterion()) || StringUtils.isNotEmpty(filterCriteria.getAttributeName()));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.apache.atlas.model.discovery.AtlasAggregationEntry;
|
|||
import org.apache.atlas.model.instance.AtlasClassification;
|
||||
import org.apache.atlas.model.instance.AtlasEntity;
|
||||
import org.apache.atlas.model.instance.AtlasEntityHeader;
|
||||
import org.apache.atlas.model.instance.AtlasObjectId;
|
||||
import org.apache.atlas.model.instance.EntityMutationResponse;
|
||||
import org.apache.atlas.repository.graph.AtlasGraphProvider;
|
||||
import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream;
|
||||
|
|
@ -42,6 +43,7 @@ import org.testng.annotations.*;
|
|||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -929,6 +931,109 @@ public class AtlasDiscoveryServiceTest extends BasicTestSetup {
|
|||
Assert.assertTrue(list.get(0).getDisplayText().equalsIgnoreCase("time_id"));
|
||||
}
|
||||
|
||||
//test excludeHeaderAttributes
|
||||
@Test
|
||||
public void excludeHeaderAttributesStringAttr() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
|
||||
params.setEntityFilters(filterCriteria);
|
||||
params.setSortBy("name");
|
||||
params.setAttributes(new HashSet<String>() {{ add("name");}});
|
||||
params.setLimit(1);
|
||||
|
||||
AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
|
||||
AtlasSearchResult.AttributeSearchResult expected = new AtlasSearchResult.AttributeSearchResult();
|
||||
expected.setName(Arrays.asList("name"));
|
||||
expected.setValues(Arrays.asList(Arrays.asList("log_fact_daily_mv")));
|
||||
assertSearchResult(searchResult,expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludeHeaderAttributesRelationAttr() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("name", Operator.EQ, "time_dim");
|
||||
params.setEntityFilters(filterCriteria);
|
||||
params.setAttributes(new HashSet<String>() {{ add("name"); add("db");}});
|
||||
params.setLimit(1);
|
||||
|
||||
AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
|
||||
|
||||
assertNotNull(searchResult);
|
||||
assertNotNull(searchResult.getEntities());
|
||||
assertNotNull(searchResult.getReferredEntities());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludeHeaderAttributesSystemAttr() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
params.setAttributes(new HashSet<String>() {{ add("name"); add("__state");}});
|
||||
params.setLimit(1);
|
||||
SearchParameters.FilterCriteria filterCriteria = getSingleFilterCondition("tableType", Operator.EQ, "Managed");
|
||||
params.setEntityFilters(filterCriteria);
|
||||
params.setSortBy("name");
|
||||
|
||||
AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
|
||||
AtlasSearchResult.AttributeSearchResult expected = new AtlasSearchResult.AttributeSearchResult();
|
||||
expected.setName(Arrays.asList("name","__state"));
|
||||
expected.setValues(Arrays.asList(Arrays.asList("log_fact_daily_mv","ACTIVE")));
|
||||
assertSearchResult(searchResult,expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void excludeHeaderAttributesAllEntityTypeSysAttr() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE+","+ALL_ENTITY_TYPES);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
params.setAttributes(new HashSet<String>() {{ add("__state");}});
|
||||
params.setLimit(2);
|
||||
|
||||
AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
|
||||
AtlasSearchResult.AttributeSearchResult expected = new AtlasSearchResult.AttributeSearchResult();
|
||||
expected.setName(Arrays.asList("__state"));
|
||||
expected.setValues(Arrays.asList(Arrays.asList("ACTIVE"), Arrays.asList("ACTIVE")));
|
||||
assertSearchResult(searchResult,expected);
|
||||
}
|
||||
@Test
|
||||
public void excludeHeaderAttributesAllEntityTypeSysAttrs() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE+","+ALL_ENTITY_TYPES);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
params.setAttributes(new HashSet<String>() {{ add("__state"); add("__guid");}});
|
||||
params.setLimit(2);
|
||||
|
||||
AtlasSearchResult searchResult = discoveryService.searchWithParameters(params);
|
||||
assertEquals(searchResult.getAttributes().getValues().size(), 2);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Attribute name not found for type __ENTITY_ROOT")
|
||||
public void excludeHeaderAttributesAllEntityType() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE+","+ALL_ENTITY_TYPES);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
params.setAttributes(new HashSet<String>() {{ add("name");}});
|
||||
params.setLimit(1);
|
||||
|
||||
discoveryService.searchWithParameters(params);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AtlasBaseException.class, expectedExceptionsMessageRegExp = "Attribute name1 not found for type hive_table")
|
||||
public void excludeHeaderAttributesInvalidAttr() throws AtlasBaseException {
|
||||
SearchParameters params = new SearchParameters();
|
||||
params.setTypeName(HIVE_TABLE_TYPE);
|
||||
params.setExcludeHeaderAttributes(true);
|
||||
params.setAttributes(new HashSet<String>() {{ add("name1");}});
|
||||
params.setLimit(1);
|
||||
|
||||
discoveryService.searchWithParameters(params);
|
||||
}
|
||||
|
||||
|
||||
private String gethiveTableSalesFactGuid() throws AtlasBaseException {
|
||||
if (salesFactGuid == null) {
|
||||
SearchParameters params = new SearchParameters();
|
||||
|
|
@ -958,6 +1063,18 @@ public class AtlasDiscoveryServiceTest extends BasicTestSetup {
|
|||
}
|
||||
}
|
||||
|
||||
private void assertSearchResult(AtlasSearchResult searchResult, AtlasSearchResult.AttributeSearchResult expected) {
|
||||
assertNotNull(searchResult);
|
||||
AtlasSearchResult.AttributeSearchResult result = searchResult.getAttributes();
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getName().containsAll(expected.getName()));
|
||||
int i = 0;
|
||||
for (List<Object> value : result.getValues()) {
|
||||
assertTrue(value.containsAll(expected.getValues().get(i)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAggregationMetrics(AtlasQuickSearchResult searchResult) {
|
||||
Map<String, List<AtlasAggregationEntry>> agg = searchResult.getAggregationMetrics();
|
||||
Assert.assertTrue(CollectionUtils.isNotEmpty(agg.get("__typeName")));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
"offset": 0,
|
||||
"entityFilters": null,
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 1
|
||||
},
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
"offset": 0,
|
||||
"entityFilters": null,
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 0
|
||||
},
|
||||
|
|
@ -129,7 +129,7 @@
|
|||
]
|
||||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 1
|
||||
},
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
"offset": 0,
|
||||
"entityFilters": null,
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 1
|
||||
},
|
||||
|
|
@ -159,7 +159,7 @@
|
|||
"offset": 0,
|
||||
"entityFilters": null,
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 3
|
||||
},
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
"attributeValue" : "+"
|
||||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [""]
|
||||
"attributes": []
|
||||
},
|
||||
"expectedCount": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -38,7 +37,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -59,7 +57,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 2
|
||||
|
|
@ -81,7 +78,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 1
|
||||
|
|
@ -113,7 +109,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -145,7 +140,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -177,7 +171,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -199,7 +192,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -231,7 +223,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 1
|
||||
|
|
@ -263,7 +254,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 18
|
||||
|
|
@ -295,7 +285,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -327,7 +316,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
@ -359,7 +347,6 @@
|
|||
},
|
||||
"tagFilters": null,
|
||||
"attributes": [
|
||||
""
|
||||
]
|
||||
},
|
||||
"expectedCount": 3
|
||||
|
|
|
|||
Loading…
Reference in New Issue