#python #django #postgresql #full-text-search
Вопрос:
Я использую полнотекстовый поиск в PostgreSQL через Django.
Я хочу связать веса с поисковыми системами. Я знаю, что можно связать разные веса с разными полями, но я хочу иметь разный вес в поисковых системах.
Пример:
from core.models import SkillName
vector = SearchVector(
"name",
)
search = SearchQuery("Java") | SearchQuery("Spring")
search_result = (
SkillName.objects.all()
.annotate(search=vector)
.filter(search=search)
.annotate(rank=SearchRank(vector, search))
.order_by("-rank")
)
for s in search_result.distinct():
print(f"{s} rank: {s.rank}")
И теперь я хочу, чтобы «Java» была более важной, чем «Весна», и соответственно получала рейтинг.
Я думаю, я мог бы выполнить 2 разных поиска и умножить ранги на коэффициенты, но есть ли лучший способ ?
Действительно ли так странно хотеть связать разные приоритеты с поисковыми системами ?
Сгенерированный SQL для справки, я, честно говоря, не думаю, что это возможно в Django прямо сейчас, в любом случае, и нам может понадобиться помощь гуру PostgreSQL.
SELECT DISTINCT "core_skillname"."id",
"core_skillname"."name",
to_tsvector(COALESCE("core_skillname"."name", '')) AS "search",
ts_rank(to_tsvector(COALESCE("core_skillname"."name", '')), (plainto_tsquery('Java') || plainto_tsquery('Spring'))) AS "rank"
FROM "core_skillname"
WHERE to_tsvector(COALESCE("core_skillname"."name", '')) @@ (plainto_tsquery('Java') || plainto_tsquery('Spring'))
ORDER BY "rank" DESC;```
Ответ №1:
Для применения рангов с весами не требуется двух запросов, достаточно двух вложенных выражений в одном запросе.
SELECT DISTINCT "core_skillname"."id",
"core_skillname"."name",
to_tsvector(COALESCE("core_skillname"."name", '')) AS "search",
ts_rank(to_tsvector(COALESCE("core_skillname"."name", '')), plainto_tsquery('Spring'))
ts_rank(to_tsvector(COALESCE("core_skillname"."name", '')), plainto_tsquery('Java')) * 1.5 AS "rank"
FROM "core_skillname"
WHERE to_tsvector(COALESCE("core_skillname"."name", '')) @@ (plainto_tsquery('Java') || plainto_tsquery('Spring'))
ORDER BY "rank" DESC;
Поскольку так легко поцарапать свой собственный зуд, зачем изобретать для этого какой-то другой механизм? Когда веса являются частью таблицы, а не частью запроса, вы действительно не могли бы сделать это таким образом, поэтому его собственный механизм имеет больше смысла.