From 6eb78d730766003f5df3914777ce9ff39d259585 Mon Sep 17 00:00:00 2001 From: Adrien Date: Mon, 1 May 2023 22:42:02 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20/stop=20API=20endpoint=20u?= =?UTF-8?q?ses=20stop=20and=20towns=20names=20to=20resolve=20queries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/backend/models/stop.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/backend/backend/models/stop.py b/backend/backend/models/stop.py index b686741..d70fe9e 100644 --- a/backend/backend/models/stop.py +++ b/backend/backend/models/stop.py @@ -5,9 +5,12 @@ from typing import Iterable, Sequence, TYPE_CHECKING from sqlalchemy import ( BigInteger, Column, + Computed, + desc, Enum, Float, ForeignKey, + func, Integer, JSON, select, @@ -22,6 +25,7 @@ from sqlalchemy.orm import ( with_polymorphic, ) from sqlalchemy.schema import Index +from sqlalchemy_utils.types.ts_vector import TSVectorType from ..db import Base, db from ..idfm_interface.idfm_types import TransportMode, IdfmState, StopAreaType @@ -71,13 +75,17 @@ class _Stop(Base): back_populates="stops", lazy="selectin" ) + names_tsv = mapped_column( + TSVectorType("name", "town_name", regconfig="french"), + Computed("to_tsvector('french', name || ' ' || town_name)", persisted=True), + ) + __tablename__ = "_stops" __mapper_args__ = {"polymorphic_identity": "_stops", "polymorphic_on": kind} __table_args__ = ( - # To optimize the ilike requests Index( - "name_idx_gin", - name, + "names_tsv_idx", + names_tsv, postgresql_ops={"name": "gin_trgm_ops"}, postgresql_using="gin", ), @@ -92,9 +100,15 @@ class _Stop(Base): return None stop_stop_area = with_polymorphic(_Stop, [Stop, StopArea]) + match_stmt = stop_stop_area.names_tsv.match(name, postgresql_regconfig="french") + ranking_stmt = func.ts_rank_cd( + stop_stop_area.names_tsv, func.plainto_tsquery("french", name) + ) + stmt = ( select(stop_stop_area) - .where(stop_stop_area.name.ilike(f"%{name}%")) + .filter(match_stmt) + .order_by(desc(ranking_stmt)) .options( selectinload(stop_stop_area.areas), selectinload(stop_stop_area.lines),