From 4ca6c37cc8f60134117d965706703a2a3ad0f3a6 Mon Sep 17 00:00:00 2001 From: DebaucheryLibrarian Date: Fri, 26 Feb 2021 17:22:54 +0100 Subject: [PATCH] Added relevance to REST release search API, sorting by relevance rank. Improved search result table column naming. --- assets/js/ui/actions.js | 2 +- migrations/20190325001339_releases.js | 15 ++++----------- src/releases.js | 9 +++++++-- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/assets/js/ui/actions.js b/assets/js/ui/actions.js index ee17d8cc..ede89382 100644 --- a/assets/js/ui/actions.js +++ b/assets/js/ui/actions.js @@ -44,7 +44,7 @@ function initUiActions(_store, _router) { } } ) { - release: releaseById { + release { id title slug diff --git a/migrations/20190325001339_releases.js b/migrations/20190325001339_releases.js index 146995c7..40540bfe 100644 --- a/migrations/20190325001339_releases.js +++ b/migrations/20190325001339_releases.js @@ -1001,10 +1001,9 @@ exports.up = knex => Promise.resolve() // allow vim fold return knex.raw(` /* We need both the release entries and their search ranking, and PostGraphile does not seem to allow virtual foreign keys on function results. - * Using a view as a proxy for the search results allows us to get both a reference to the releases table, and the ranking. - * A composite type does not seem to be compatible with PostGraphile's @sortable. */ - CREATE VIEW releases_search_results AS - SELECT NULL::integer as id, NULL::real as rank; + * Using a table as a proxy for the search results allows us to get both a reference to the releases table, and the ranking. + * A composite type does not seem to be compatible with PostGraphile's @sortable, and a view does not allow for many native constraints */ + CREATE TABLE releases_search_results (release_id integer, rank real, FOREIGN KEY (release_id) REFERENCES releases (id)); CREATE FUNCTION search_releases(query text) RETURNS SETOF releases_search_results AS $$ SELECT releases.id, ranks.rank FROM ( @@ -1182,8 +1181,6 @@ exports.up = knex => Promise.resolve() COMMENT ON FUNCTION actors_scenes IS E'@sortable'; COMMENT ON FUNCTION tags_scenes IS E'@sortable'; COMMENT ON FUNCTION search_releases IS E'@sortable'; - - COMMENT ON VIEW releases_search_results is E'@foreignKey (id) REFERENCES releases (id)'; `); }); @@ -1245,7 +1242,6 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style DROP TABLE IF EXISTS entities_types CASCADE; DROP TABLE IF EXISTS entities CASCADE; - DROP FUNCTION IF EXISTS search_releases_legacy; DROP FUNCTION IF EXISTS search_releases; DROP FUNCTION IF EXISTS search_sites; DROP FUNCTION IF EXISTS search_entities; @@ -1262,9 +1258,6 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style DROP FUNCTION IF EXISTS movies_tags; DROP FUNCTION IF EXISTS movies_photos; - DROP VIEW IF EXISTS releases_search_results; - - DROP TEXT SEARCH CONFIGURATION IF EXISTS traxxx; - DROP TEXT SEARCH DICTIONARY IF EXISTS traxxx_dict; + DROP TABLE IF EXISTS releases_search_results; `); }; diff --git a/src/releases.js b/src/releases.js index a853635c..06ded702 100644 --- a/src/releases.js +++ b/src/releases.js @@ -13,6 +13,7 @@ function curateRelease(release, withMedia = false, withPoster = true) { return { id: release.id, + ...(release.relevance && { relevance: release.relevance }), entryId: release.entry_id, shootId: release.shoot_id, title: release.title, @@ -134,9 +135,13 @@ async function fetchScenes(limit = 100) { async function searchScenes(query, limit = 100) { const releases = await knex - .from(knex.raw('search_releases(:query) as releases', { query })) + .select(knex.raw('search_results.rank as relevance')) + .from(knex.raw('search_releases(:query) as search_results', { query })) + .leftJoin('releases', 'releases.id', 'search_results.release_id') .modify(withRelations, false, true) - .limit(Math.min(limit, 1000000)); + .limit(Math.min(limit, 1000000)) + .groupBy('search_results.rank') + .orderBy('search_results.rank', 'desc'); return releases.map(release => curateRelease(release)); }