diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/DataPlatformType.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/DataPlatformType.java index 921b1ab3b5edd1..c0c57086a9f2a5 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/DataPlatformType.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/types/dataplatform/DataPlatformType.java @@ -2,15 +2,26 @@ import static com.linkedin.metadata.Constants.*; +import com.google.common.collect.ImmutableSet; import com.linkedin.common.urn.Urn; import com.linkedin.common.urn.UrnUtils; import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.datahub.graphql.generated.AutoCompleteResults; import com.linkedin.datahub.graphql.generated.DataPlatform; import com.linkedin.datahub.graphql.generated.Entity; +import com.linkedin.datahub.graphql.generated.FacetFilterInput; +import com.linkedin.datahub.graphql.generated.SearchResults; +import com.linkedin.datahub.graphql.resolvers.ResolverUtils; import com.linkedin.datahub.graphql.types.EntityType; +import com.linkedin.datahub.graphql.types.SearchableEntityType; import com.linkedin.datahub.graphql.types.dataplatform.mappers.DataPlatformMapper; +import com.linkedin.datahub.graphql.types.mappers.AutoCompleteResultsMapper; +import com.linkedin.datahub.graphql.types.mappers.UrnSearchResultsMapper; import com.linkedin.entity.EntityResponse; import com.linkedin.entity.client.EntityClient; +import com.linkedin.metadata.query.AutoCompleteResult; +import com.linkedin.metadata.query.filter.Filter; +import com.linkedin.metadata.search.SearchResult; import graphql.execution.DataFetcherResult; import java.util.ArrayList; import java.util.HashSet; @@ -18,8 +29,11 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; -public class DataPlatformType implements EntityType { +public class DataPlatformType + implements SearchableEntityType, EntityType { private final EntityClient _entityClient; @@ -75,4 +89,39 @@ public com.linkedin.datahub.graphql.generated.EntityType type() { public Function getKeyProvider() { return Entity::getUrn; } + + @Override + public SearchResults search( + @Nonnull String query, + @Nullable List filters, + int start, + int count, + @Nonnull final QueryContext context) + throws Exception { + final Map facetFilters = + ResolverUtils.buildFacetFilters(filters, ImmutableSet.of()); + final SearchResult searchResult = + _entityClient.search( + context.getOperationContext().withSearchFlags(flags -> flags.setFulltext(true)), + DATA_PLATFORM_ENTITY_NAME, + query, + facetFilters, + start, + count); + return UrnSearchResultsMapper.map(context, searchResult); + } + + @Override + public AutoCompleteResults autoComplete( + @Nonnull String query, + @Nullable String field, + @Nullable Filter filters, + int limit, + @Nonnull final QueryContext context) + throws Exception { + final AutoCompleteResult result = + _entityClient.autoComplete( + context.getOperationContext(), DATA_PLATFORM_ENTITY_NAME, query, filters, limit); + return AutoCompleteResultsMapper.map(context, result); + } } diff --git a/datahub-web-react/src/app/searchV2/filters/value/EntityValueMenu.tsx b/datahub-web-react/src/app/searchV2/filters/value/EntityValueMenu.tsx index d370f6bcf5f450..763c77bb34a3c5 100644 --- a/datahub-web-react/src/app/searchV2/filters/value/EntityValueMenu.tsx +++ b/datahub-web-react/src/app/searchV2/filters/value/EntityValueMenu.tsx @@ -28,8 +28,7 @@ export default function EntityValueMenu({ className, }: Props) { const entityRegistry = useEntityRegistry(); - const isSearchable = - field.entityTypes?.length && field.entityTypes.every((t) => entityRegistry.getEntity(t).isSearchEnabled()); + const isSearchable = !!field.entityTypes?.length; const { displayName } = field; // Ideally we would not have staged values, and filters would update automatically. @@ -43,7 +42,8 @@ export default function EntityValueMenu({ const finalSearchOptions = [...localSearchOptions, ...deduplicateOptions(localSearchOptions, searchOptions)]; // Compute the final options to show to the user. - const finalOptions = searchQuery ? finalSearchOptions : defaultOptions; + const finalDefaultOptions = defaultOptions.length ? defaultOptions : searchOptions; + const finalOptions = searchQuery ? finalSearchOptions : finalDefaultOptions; // Finally, create the option set. // TODO: Add an option set for "no x". diff --git a/datahub-web-react/src/app/searchV2/filters/value/utils.tsx b/datahub-web-react/src/app/searchV2/filters/value/utils.tsx index 1cdde2b052f984..da49e28e5b1714 100644 --- a/datahub-web-react/src/app/searchV2/filters/value/utils.tsx +++ b/datahub-web-react/src/app/searchV2/filters/value/utils.tsx @@ -5,6 +5,7 @@ import { EntityRegistry } from '../../../../entityRegistryContext'; import { useAggregateAcrossEntitiesQuery, useGetAutoCompleteMultipleResultsQuery, + useGetSearchResultsForMultipleQuery, } from '../../../../graphql/search.generated'; import { EntityType } from '../../../../types.generated'; import { capitalizeFirstLetterOnly } from '../../../shared/textUtil'; @@ -94,6 +95,19 @@ export const useLoadSearchOptions = (field: EntityFilterField, query?: string, s fetchPolicy: 'cache-first', }); + // do initial search to get initial data to display + const { data: searchData, loading: searchLoading } = useGetSearchResultsForMultipleQuery({ + skip: skip || !!query, // only do a search if not doing auto-complete, + variables: { + input: { + query: '*', + types: field.entityTypes, + count: 10, + }, + }, + fetchPolicy: 'cache-first', + }); + if (skip) { return { loading: false, options: [] }; } @@ -107,7 +121,13 @@ export const useLoadSearchOptions = (field: EntityFilterField, query?: string, s icon: field.icon, }; }); - return { options: options || [], loading }; + const searchOptions = searchData?.searchAcrossEntities?.searchResults.map((result) => ({ + value: result.entity.urn, + entity: result.entity, + icon: field.icon, + })); + + return { options: options || searchOptions || [], loading: loading || searchLoading }; }; /**