Support title/description metadata searching in GET /arbitrary/resources/search

"query" searches name, identifier, title and description fields
"title" searches title only
"description" searches description only

All support "&prefix=true", to indicate searching by prefix only.
This commit is contained in:
CalDescent 2023-05-07 17:57:14 +01:00
parent cdcb268bd9
commit 2fd5bfb11a
4 changed files with 30 additions and 11 deletions

View File

@ -162,9 +162,11 @@ public class ArbitraryResource {
@ApiErrors({ApiError.REPOSITORY_ISSUE}) @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List<ArbitraryResourceData> searchResources( public List<ArbitraryResourceData> searchResources(
@QueryParam("service") Service service, @QueryParam("service") Service service,
@Parameter(description = "Query (searches both name and identifier fields)") @QueryParam("query") String query, @Parameter(description = "Query (searches name, identifier, title and description fields)") @QueryParam("query") String query,
@Parameter(description = "Identifier (searches identifier field only)") @QueryParam("identifier") String identifier, @Parameter(description = "Identifier (searches identifier field only)") @QueryParam("identifier") String identifier,
@Parameter(description = "Name (searches name field only)") @QueryParam("name") List<String> names, @Parameter(description = "Name (searches name field only)") @QueryParam("name") List<String> names,
@Parameter(description = "Title (searches title metadata field only)") @QueryParam("title") String title,
@Parameter(description = "Description (searches description metadata field only)") @QueryParam("description") String description,
@Parameter(description = "Prefix only (if true, only the beginning of fields are matched)") @QueryParam("prefix") Boolean prefixOnly, @Parameter(description = "Prefix only (if true, only the beginning of fields are matched)") @QueryParam("prefix") Boolean prefixOnly,
@Parameter(description = "Exact match names only (if true, partial name matches are excluded)") @QueryParam("exactmatchnames") Boolean exactMatchNamesOnly, @Parameter(description = "Exact match names only (if true, partial name matches are excluded)") @QueryParam("exactmatchnames") Boolean exactMatchNamesOnly,
@Parameter(description = "Default resources (without identifiers) only") @QueryParam("default") Boolean defaultResource, @Parameter(description = "Default resources (without identifiers) only") @QueryParam("default") Boolean defaultResource,
@ -201,7 +203,7 @@ public class ArbitraryResource {
} }
List<ArbitraryResourceData> resources = repository.getArbitraryRepository() List<ArbitraryResourceData> resources = repository.getArbitraryRepository()
.searchArbitraryResources(service, query, identifier, names, usePrefixOnly, exactMatchNames, .searchArbitraryResources(service, query, identifier, names, title, description, usePrefixOnly, exactMatchNames,
defaultRes, followedOnly, excludeBlocked, includeMetadata, includeStatus, limit, offset, reverse); defaultRes, followedOnly, excludeBlocked, includeMetadata, includeStatus, limit, offset, reverse);
if (resources == null) { if (resources == null) {

View File

@ -39,7 +39,7 @@ public interface ArbitraryRepository {
public List<ArbitraryResourceData> getArbitraryResources(Service service, String identifier, List<String> names, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked, Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException; public List<ArbitraryResourceData> getArbitraryResources(Service service, String identifier, List<String> names, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked, Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException;
public List<ArbitraryResourceData> searchArbitraryResources(Service service, String query, String identifier, List<String> names, boolean prefixOnly, List<String> namesFilter, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked, Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException; public List<ArbitraryResourceData> searchArbitraryResources(Service service, String query, String identifier, List<String> names, String title, String description, boolean prefixOnly, List<String> namesFilter, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked, Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException;
// Arbitrary resources cache save/load // Arbitrary resources cache save/load

View File

@ -638,7 +638,7 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
} }
@Override @Override
public List<ArbitraryResourceData> searchArbitraryResources(Service service, String query, String identifier, List<String> names, boolean prefixOnly, public List<ArbitraryResourceData> searchArbitraryResources(Service service, String query, String identifier, List<String> names, String title, String description, boolean prefixOnly,
List<String> exactMatchNames, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked, List<String> exactMatchNames, boolean defaultResource, Boolean followedOnly, Boolean excludeBlocked,
Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException { Boolean includeMetadata, Boolean includeStatus, Integer limit, Integer offset, Boolean reverse) throws DataException {
StringBuilder sql = new StringBuilder(512); StringBuilder sql = new StringBuilder(512);
@ -669,9 +669,8 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
} else { } else {
// Non-default resource requested // Non-default resource requested
// In this case we search the identifier as well as the name // In this case we search the identifier as well as the name
sql.append(" AND (LCASE(name) LIKE ? OR LCASE(identifier) LIKE ?)"); sql.append(" AND (LCASE(name) LIKE ? OR LCASE(identifier) LIKE ? OR LCASE(title) LIKE ? OR LCASE(description) LIKE ?)");
bindParams.add(queryWildcard); bindParams.add(queryWildcard); bindParams.add(queryWildcard); bindParams.add(queryWildcard); bindParams.add(queryWildcard);
bindParams.add(queryWildcard);
} }
} }
@ -683,6 +682,22 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
bindParams.add(queryWildcard); bindParams.add(queryWildcard);
} }
// Handle title metadata matches
if (title != null) {
// Search anywhere in the title, unless "prefixOnly" has been requested
String queryWildcard = prefixOnly ? String.format("%s%%", title.toLowerCase()) : String.format("%%%s%%", title.toLowerCase());
sql.append(" AND LCASE(title) LIKE ?");
bindParams.add(queryWildcard);
}
// Handle description metadata matches
if (description != null) {
// Search anywhere in the description, unless "prefixOnly" has been requested
String queryWildcard = prefixOnly ? String.format("%s%%", description.toLowerCase()) : String.format("%%%s%%", description.toLowerCase());
sql.append(" AND LCASE(description) LIKE ?");
bindParams.add(queryWildcard);
}
// Handle name searches // Handle name searches
if (names != null && !names.isEmpty()) { if (names != null && !names.isEmpty()) {
sql.append(" AND ("); sql.append(" AND (");
@ -763,8 +778,8 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
Long updated = resultSet.getLong(7); Long updated = resultSet.getLong(7);
// Optional metadata fields // Optional metadata fields
String title = resultSet.getString(8); String titleResult = resultSet.getString(8);
String description = resultSet.getString(9); String descriptionResult = resultSet.getString(9);
String category = resultSet.getString(10); String category = resultSet.getString(10);
String tag1 = resultSet.getString(11); String tag1 = resultSet.getString(11);
String tag2 = resultSet.getString(12); String tag2 = resultSet.getString(12);
@ -792,8 +807,8 @@ public class HSQLDBArbitraryRepository implements ArbitraryRepository {
if (includeMetadata != null && includeMetadata) { if (includeMetadata != null && includeMetadata) {
// TODO: we could avoid the join altogether // TODO: we could avoid the join altogether
ArbitraryResourceMetadata metadata = new ArbitraryResourceMetadata(); ArbitraryResourceMetadata metadata = new ArbitraryResourceMetadata();
metadata.setTitle(title); metadata.setTitle(titleResult);
metadata.setDescription(description); metadata.setDescription(descriptionResult);
metadata.setCategory(Category.uncategorizedValueOf(category)); metadata.setCategory(Category.uncategorizedValueOf(category));
List<String> tags = new ArrayList<>(); List<String> tags = new ArrayList<>();

View File

@ -218,6 +218,8 @@ window.addEventListener("message", (event) => {
if (data.identifier != null) url = url.concat("&identifier=" + data.identifier); if (data.identifier != null) url = url.concat("&identifier=" + data.identifier);
if (data.name != null) url = url.concat("&name=" + data.name); if (data.name != null) url = url.concat("&name=" + data.name);
if (data.names != null) data.names.forEach((x, i) => url = url.concat("&name=" + x)); if (data.names != null) data.names.forEach((x, i) => url = url.concat("&name=" + x));
if (data.title != null) url = url.concat("&title=" + data.title);
if (data.description != null) url = url.concat("&description=" + data.description);
if (data.prefix != null) url = url.concat("&prefix=" + new Boolean(data.prefix).toString()); if (data.prefix != null) url = url.concat("&prefix=" + new Boolean(data.prefix).toString());
if (data.exactMatchNames != null) url = url.concat("&exactmatchnames=" + new Boolean(data.exactMatchNames).toString()); if (data.exactMatchNames != null) url = url.concat("&exactmatchnames=" + new Boolean(data.exactMatchNames).toString());
if (data.default != null) url = url.concat("&default=" + new Boolean(data.default).toString()); if (data.default != null) url = url.concat("&default=" + new Boolean(data.default).toString());