-
I have a procedure which facilitates a search based on some query through several paths. The result is a primary key related to another table, but also an additional field for reporting the similarity. I was hoping to take advantage of resource embedding with this procedure but I can't seem to get the embedding to work when I add the additional column.. Here is the procedure I'm working on -- it performs a search through several tables with one query and returns results. If I just return the results (for the table api.path) the embedding works fine as if it was a filter of the create or replace function api.query(q text, lim int)
-- <<<<
-- this works:
-- returns setof api.path
-- as $$
-- select
-- api.path.*
-- ====
-- this does not
returns table (
path varchar, -- primary key of table (i've also tried using all the columns with this additional reason column)
reason varchar -- description of search results
)
as $$
select
api.path.path,
result.reason
-- >>>>
from
(
with
-- all of these tables have foreign key relationships to `api.path.path`
searches as (
-- search for similar names
(select
api.path.path,
similarity(api.path.name, q) * 0.1 as sim,
format('name (%s)', round(similarity(api.path.name, q)::numeric, 3)::text) as reason
from api.path
-- use when db is large
--where api.path.name % q
order by sim desc
limit lim)
union
-- search for similar content
(select
api.search.path,
ts_rank_cd(api.search.tsvec, plainto_tsquery(q), 32) * 10. as sim,
format('content (%s)', round(ts_rank_cd(api.search.tsvec, plainto_tsquery(q), 32)::numeric, 3)::text) as reason
from api.search
-- use when db is large
--where api.search.tsvec @@ plainto_tsquery(q)
order by sim desc
limit lim)
union
-- search for similar tags
(select
api.tag.path,
max(similarity(api.tag.tag, q)) * 0.25 as sim,
format('tag (%s)', round((max(similarity(api.tag.tag, q)) * 0.25)::numeric, 3)::text) as reason
from api.tag
-- use when db is large
--where api.tag.tag % q
group by api.tag.path
order by sim desc
limit lim)
)
select
searches.path,
string_agg(searches.reason, ', ') as reason
from searches
where sim > 0
group by searches.path
order by sum(coalesce(sim, 0)) desc
) result
-- join with api.path in an attempt to recover resource for embedding
-- in reality, i should just be able to use `searches.path`
inner join api.path on result.path = api.path.path
$$ language sql immutable security definer; Ideally I could use this like:
This primary key is also referenced in many other tables, thus getting this to work would allow me to embed many other tables as well from this endpoint (which is desired). Can someone more familiar with either postgrest or postgres point me in the right direction? Perhaps it's a flaw in my procedure design or something else. Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
Edit: See comments for full answer Update I played around with this a bit and made some meaningful progress by doing the following (as weird as I felt it was when I tried it). I created a "placeholder" view to effectively represent the structure I hoped to return so that I can still use create or replace view api.query_results as
select *, '' as reason
from api.path; Un-intuitively, this did allow me to change the create or replace function api.query(q text, lim int)
returns setof api.query_results
as $$
select
-- all fields in api.path
api.query_results.path,
api.query_results.type,
api.query_results.name,
-- replace reason
result.reason
from
-- ...
inner join api.query_results on result.path = api.query_results.path
$$ language sql immutable security definer; Amazingly this version works albeit with the unexpected side-effect of appearing in a list (perhaps this is expected, I'm just new to postgrest -- but
Some things that were still unexpected:
If anyone can offer me some clarity as to why this was necessary and why some aspects of this are not as I'd expect I'd greatly appreciate it. Thank you |
Beta Was this translation helpful? Give feedback.
Edit: See comments for full answer
Update
I played around with this a bit and made some meaningful progress by doing the following (as weird as I felt it was when I tried it).
I created a "placeholder" view to effectively represent the structure I hoped to return so that I can still use
setof
notation to describe the results:Un-intuitively, this did allow me to change the
reason
from an empty string to the reason I wanted: