From 170cc4244d769263e0d0507cfd4a05d80695742a Mon Sep 17 00:00:00 2001 From: Niels Simenon Date: Wed, 26 Feb 2020 03:38:21 +0100 Subject: [PATCH] Using rudimentary full text search. --- assets/js/releases/actions.js | 54 +++++++++++++++-------------- migrations/20200225223307_search.js | 30 +++++++++++++--- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/assets/js/releases/actions.js b/assets/js/releases/actions.js index 8ef89651..8568de26 100644 --- a/assets/js/releases/actions.js +++ b/assets/js/releases/actions.js @@ -32,42 +32,44 @@ function initReleasesActions(store, _router) { $limit: Int = 20 ) { releases: searchReleases( - search: $query + query: $query first: $limit ) { - id - title - date - url - site { + releaseById { id - slug - name + title + date url - network { + site { id slug name url + network { + id + slug + name + url + } } - } - actors: releasesActors { - actor { - id - slug - name + actors: releasesActors { + actor { + id + slug + name + } } - } - tags: releasesTags { - tag { - id - name - slug + tags: releasesTags { + tag { + id + name + slug + } } - } - poster: releasesPosterByReleaseId { - media { - thumbnail + poster: releasesPosterByReleaseId { + media { + thumbnail + } } } } @@ -79,7 +81,7 @@ function initReleasesActions(store, _router) { if (!res) return []; - return res.releases.map(release => curateRelease(release)); + return res.releases.map(release => curateRelease(release.releaseById)); } async function fetchReleaseById({ _commit }, releaseId) { diff --git a/migrations/20200225223307_search.js b/migrations/20200225223307_search.js index bf713d14..9cf2685b 100644 --- a/migrations/20200225223307_search.js +++ b/migrations/20200225223307_search.js @@ -1,14 +1,34 @@ exports.up = knex => Promise.resolve() .then(() => knex.raw(` - CREATE FUNCTION search_releases(search text) RETURNS SETOF releases AS $$ - SELECT * FROM releases - WHERE - title ILIKE ('%' || search || '%') OR - url ILIKE ('%' || search || '%') + CREATE VIEW releases_document AS + SELECT + releases.id, + releases.site_id, + to_tsvector(releases.title) || + to_tsvector(sites.name) || + to_tsvector(sites.slug) || + to_tsvector(replace(CAST(releases.date AS VARCHAR), '-', ' ')) || + to_tsvector(string_agg(actors.name, ' ')) || + to_tsvector(string_agg(tags.name, ' ')) as document + FROM releases + JOIN releases_actors AS local_actors ON local_actors.release_id = releases.id + JOIN releases_tags AS local_tags ON local_tags.release_id = releases.id + JOIN sites ON releases.site_id = sites.id + JOIN actors ON local_actors.actor_id = actors.id + JOIN tags ON local_tags.tag_id = tags.id + GROUP BY releases.id, sites.name, sites.slug; + + COMMENT ON VIEW releases_document IS E'@foreignKey (id) references releases (id)\n@foreignKey (site_id) references sites (id)'; + + CREATE FUNCTION search_releases(query text) RETURNS SETOF releases_document AS $$ + SELECT * FROM releases_document AS search + WHERE search.document @@ plainto_tsquery(replace(query, '.', ' ')) + ORDER BY ts_rank(search.document, plainto_tsquery(replace(query, '.', ' '))) DESC; $$ LANGUAGE SQL STABLE; `)); exports.down = knex => Promise.resolve() .then(() => knex.raw(` DROP FUNCTION IF EXISTS search_releases; + DROP VIEW IF EXISTS releases_document; `));