feat(search): use postgres native fulltext search
All checks were successful
Build / build (push) Successful in 3m46s
All checks were successful
Build / build (push) Successful in 3m46s
This commit is contained in:
parent
5397833935
commit
d40db4ca4c
3 changed files with 67 additions and 12 deletions
|
@ -46,8 +46,6 @@ defmodule BdfrBrowser.Comment do
|
||||||
def search(str), do: search(str, nil)
|
def search(str), do: search(str, nil)
|
||||||
|
|
||||||
def search(str, subreddits) when is_nil(subreddits) do
|
def search(str, subreddits) when is_nil(subreddits) do
|
||||||
search_str = "%#{str}%"
|
|
||||||
|
|
||||||
from(c in __MODULE__,
|
from(c in __MODULE__,
|
||||||
join: p in assoc(c, :post),
|
join: p in assoc(c, :post),
|
||||||
join: s in assoc(p, :subreddit),
|
join: s in assoc(p, :subreddit),
|
||||||
|
@ -62,15 +60,15 @@ defmodule BdfrBrowser.Comment do
|
||||||
post_title: p.title,
|
post_title: p.title,
|
||||||
post_date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
post_date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
||||||
},
|
},
|
||||||
where: ilike(c.body, ^search_str),
|
where:
|
||||||
|
fragment("? @@ websearch_to_tsquery('english', ?)", c.searchable_content, ^str) or
|
||||||
|
fragment("? @@ websearch_to_tsquery('german', ?)", c.searchable_content, ^str),
|
||||||
order_by: [desc: c.posted_at],
|
order_by: [desc: c.posted_at],
|
||||||
group_by: [c.id, p.id, s.name]
|
group_by: [c.id, p.id, s.name]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search(str, subreddits) when is_list(subreddits) do
|
def search(str, subreddits) when is_list(subreddits) do
|
||||||
search_str = "%#{str}%"
|
|
||||||
|
|
||||||
from(c in __MODULE__,
|
from(c in __MODULE__,
|
||||||
join: p in assoc(c, :post),
|
join: p in assoc(c, :post),
|
||||||
join: s in assoc(p, :subreddit),
|
join: s in assoc(p, :subreddit),
|
||||||
|
@ -85,7 +83,10 @@ defmodule BdfrBrowser.Comment do
|
||||||
post_title: p.title,
|
post_title: p.title,
|
||||||
post_date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
post_date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
||||||
},
|
},
|
||||||
where: s.name in ^subreddits and ilike(c.body, ^search_str),
|
where:
|
||||||
|
s.name in ^subreddits and
|
||||||
|
(fragment("? @@ websearch_to_tsquery('english', ?)", c.searchable_content, ^str) or
|
||||||
|
fragment("? @@ websearch_to_tsquery('german', ?)", c.searchable_content, ^str)),
|
||||||
order_by: [desc: c.posted_at],
|
order_by: [desc: c.posted_at],
|
||||||
group_by: [c.id, p.id, s.name]
|
group_by: [c.id, p.id, s.name]
|
||||||
)
|
)
|
||||||
|
|
|
@ -123,8 +123,6 @@ defmodule BdfrBrowser.Post do
|
||||||
def search(str), do: search(str, nil)
|
def search(str), do: search(str, nil)
|
||||||
|
|
||||||
def search(str, subreddits) when is_nil(subreddits) do
|
def search(str, subreddits) when is_nil(subreddits) do
|
||||||
search_str = "%#{str}%"
|
|
||||||
|
|
||||||
from(p in __MODULE__,
|
from(p in __MODULE__,
|
||||||
left_join: c in assoc(p, :comments),
|
left_join: c in assoc(p, :comments),
|
||||||
join: s in assoc(p, :subreddit),
|
join: s in assoc(p, :subreddit),
|
||||||
|
@ -137,15 +135,15 @@ defmodule BdfrBrowser.Post do
|
||||||
subreddit: s.name,
|
subreddit: s.name,
|
||||||
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
||||||
},
|
},
|
||||||
where: ilike(p.title, ^search_str) or ilike(p.selftext, ^search_str),
|
where:
|
||||||
|
fragment("? @@ websearch_to_tsquery('english', ?)", p.searchable_content, ^str) or
|
||||||
|
fragment("? @@ websearch_to_tsquery('german', ?)", p.searchable_content, ^str),
|
||||||
order_by: [desc: p.posted_at],
|
order_by: [desc: p.posted_at],
|
||||||
group_by: [p.id, s.name]
|
group_by: [p.id, s.name]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search(str, subreddits) when is_list(subreddits) do
|
def search(str, subreddits) when is_list(subreddits) do
|
||||||
search_str = "%#{str}%"
|
|
||||||
|
|
||||||
from(p in __MODULE__,
|
from(p in __MODULE__,
|
||||||
left_join: c in assoc(p, :comments),
|
left_join: c in assoc(p, :comments),
|
||||||
join: s in assoc(p, :subreddit),
|
join: s in assoc(p, :subreddit),
|
||||||
|
@ -158,7 +156,10 @@ defmodule BdfrBrowser.Post do
|
||||||
subreddit: s.name,
|
subreddit: s.name,
|
||||||
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
date: fragment("to_char(?, 'YYYY-MM')", p.posted_at)
|
||||||
},
|
},
|
||||||
where: s.name in ^subreddits and (ilike(p.title, ^search_str) or ilike(p.selftext, ^search_str)),
|
where:
|
||||||
|
s.name in ^subreddits and
|
||||||
|
(fragment("? @@ websearch_to_tsquery('english', ?)", p.searchable_content, ^str) or
|
||||||
|
fragment("? @@ websearch_to_tsquery('german', ?)", p.searchable_content, ^str)),
|
||||||
order_by: [desc: p.posted_at],
|
order_by: [desc: p.posted_at],
|
||||||
group_by: [p.id, s.name]
|
group_by: [p.id, s.name]
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
defmodule BdfrBrowser.Repo.Migrations.AddPostCommentFulltextSearch do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
# Posts
|
||||||
|
execute """
|
||||||
|
ALTER TABLE posts
|
||||||
|
ADD COLUMN searchable_content tsvector
|
||||||
|
GENERATED ALWAYS AS (
|
||||||
|
setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('german', coalesce(title, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('english', coalesce(selftext, '')), 'B') ||
|
||||||
|
setweight(to_tsvector('german', coalesce(selftext, '')), 'B') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(author, '')), 'C')
|
||||||
|
) STORED;
|
||||||
|
"""
|
||||||
|
|
||||||
|
execute """
|
||||||
|
CREATE INDEX posts_searchable_content_index ON posts USING gin(searchable_content);
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Comments
|
||||||
|
execute """
|
||||||
|
ALTER TABLE comments
|
||||||
|
ADD COLUMN searchable_content tsvector
|
||||||
|
GENERATED ALWAYS AS (
|
||||||
|
setweight(to_tsvector('english', coalesce(body, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('german', coalesce(body, '')), 'A') ||
|
||||||
|
setweight(to_tsvector('simple', coalesce(author, '')), 'B')
|
||||||
|
) STORED;
|
||||||
|
"""
|
||||||
|
|
||||||
|
execute """
|
||||||
|
CREATE INDEX comments_searchable_content_index ON comments USING gin(searchable_content);
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
# Posts
|
||||||
|
drop index("posts", [:searchable_content])
|
||||||
|
|
||||||
|
alter table(:posts) do
|
||||||
|
remove :searchable_content
|
||||||
|
end
|
||||||
|
|
||||||
|
# Comments
|
||||||
|
drop index("comments", [:searchable_content])
|
||||||
|
|
||||||
|
alter table(:comments) do
|
||||||
|
remove :searchable_content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Reference in a new issue