use of co.cask.cdap.data2.metadata.dataset.SortInfo in project cdap by caskdata.
the class DefaultMetadataStore method search.
private MetadataSearchResponse search(Set<MetadataScope> scopes, String namespaceId, String searchQuery, Set<EntityTypeSimpleName> types, SortInfo sortInfo, int offset, int limit, int numCursors, String cursor, boolean showHidden, Set<EntityScope> entityScope) throws BadRequestException {
if (offset < 0) {
throw new IllegalArgumentException("offset must not be negative");
}
if (limit < 0) {
throw new IllegalArgumentException("limit must not be negative");
}
List<MetadataEntry> results = new LinkedList<>();
List<String> cursors = new LinkedList<>();
for (MetadataScope scope : scopes) {
SearchResults searchResults = getSearchResults(scope, namespaceId, searchQuery, types, sortInfo, offset, limit, numCursors, cursor, showHidden, entityScope);
results.addAll(searchResults.getResults());
cursors.addAll(searchResults.getCursors());
}
// sort if required
Set<NamespacedEntityId> sortedEntities = getSortedEntities(results, sortInfo);
int total = sortedEntities.size();
// pagination is not performed at the dataset level, because:
// 1. scoring is needed for DEFAULT sort info. So perform it here for now.
// 2. Even when using custom sorting, we need to remove elements from the beginning to the offset and the cursors
// at the end
// TODO: Figure out how all of this can be done server (HBase) side
int startIndex = Math.min(offset, sortedEntities.size());
// Account for overflow
int endIndex = (int) Math.min(Integer.MAX_VALUE, (long) offset + limit);
endIndex = Math.min(endIndex, sortedEntities.size());
// add 1 to maxIndex because end index is exclusive
sortedEntities = new LinkedHashSet<>(ImmutableList.copyOf(sortedEntities).subList(startIndex, endIndex));
// Fetch metadata for entities in the result list
// Note: since the fetch is happening in a different transaction, the metadata for entities may have been
// removed. It is okay not to have metadata for some results in case this happens.
Map<NamespacedEntityId, Metadata> systemMetadata = fetchMetadata(sortedEntities, MetadataScope.SYSTEM);
Map<NamespacedEntityId, Metadata> userMetadata = fetchMetadata(sortedEntities, MetadataScope.USER);
return new MetadataSearchResponse(sortInfo.getSortBy() + " " + sortInfo.getSortOrder(), offset, limit, numCursors, total, addMetadataToEntities(sortedEntities, systemMetadata, userMetadata), cursors, showHidden, entityScope);
}
use of co.cask.cdap.data2.metadata.dataset.SortInfo in project cdap by caskdata.
the class DefaultMetadataStore method getSortedEntities.
private Set<NamespacedEntityId> getSortedEntities(List<MetadataEntry> results, SortInfo sortInfo) {
// in this case, the backing storage is expected to return results in the expected order.
if (SortInfo.SortOrder.WEIGHTED != sortInfo.getSortOrder()) {
Set<NamespacedEntityId> entities = new LinkedHashSet<>(results.size());
for (MetadataEntry metadataEntry : results) {
entities.add(metadataEntry.getTargetId());
}
return entities;
}
// if sort order is weighted, score results by weight, and return in descending order of weights
// Score results
final Map<NamespacedEntityId, Integer> weightedResults = new HashMap<>();
for (MetadataEntry metadataEntry : results) {
Integer score = weightedResults.get(metadataEntry.getTargetId());
score = (score == null) ? 0 : score;
weightedResults.put(metadataEntry.getTargetId(), score + 1);
}
// Sort the results by score
List<Map.Entry<NamespacedEntityId, Integer>> resultList = new ArrayList<>(weightedResults.entrySet());
Collections.sort(resultList, SEARCH_RESULT_DESC_SCORE_COMPARATOR);
Set<NamespacedEntityId> result = new LinkedHashSet<>(resultList.size());
for (Map.Entry<NamespacedEntityId, Integer> entry : resultList) {
result.add(entry.getKey());
}
return result;
}
use of co.cask.cdap.data2.metadata.dataset.SortInfo in project cdap by caskdata.
the class MetadataHttpHandler method searchMetadata.
@GET
@Path("/namespaces/{namespace-id}/metadata/search")
public void searchMetadata(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @QueryParam("query") String searchQuery, @QueryParam("target") List<String> targets, @QueryParam("sort") @DefaultValue("") String sort, @QueryParam("offset") @DefaultValue("0") int offset, // 2147483647 is Integer.MAX_VALUE
@QueryParam("limit") @DefaultValue("2147483647") int limit, @QueryParam("numCursors") @DefaultValue("0") int numCursors, @QueryParam("cursor") @DefaultValue("") String cursor, @QueryParam("showHidden") @DefaultValue("false") boolean showHidden, @Nullable @QueryParam("entityScope") String entityScope) throws Exception {
if (searchQuery == null || searchQuery.isEmpty()) {
throw new BadRequestException("query is not specified");
}
Set<EntityTypeSimpleName> types = Collections.emptySet();
if (targets != null) {
types = ImmutableSet.copyOf(Iterables.transform(targets, STRING_TO_TARGET_TYPE));
}
SortInfo sortInfo = SortInfo.of(URLDecoder.decode(sort, "UTF-8"));
if (SortInfo.DEFAULT.equals(sortInfo)) {
if (!(cursor.isEmpty()) || 0 != numCursors) {
throw new BadRequestException("Cursors are not supported when sort info is not specified.");
}
}
try {
MetadataSearchResponse response = metadataAdmin.search(namespaceId, URLDecoder.decode(searchQuery, "UTF-8"), types, sortInfo, offset, limit, numCursors, cursor, showHidden, validateEntityScope(entityScope));
responder.sendJson(HttpResponseStatus.OK, response, MetadataSearchResponse.class, GSON);
} catch (Exception e) {
// if MetadataDataset throws an exception, it gets wrapped
if (Throwables.getRootCause(e) instanceof BadRequestException) {
throw new BadRequestException(e.getMessage(), e);
}
throw e;
}
}
Aggregations