feat(feed): per-user search finds in Mine scope + full-text relevance search
Two related search improvements: 1) Your own live-search results now belong to your Mine feed. A new per-user search_finds table (migration 0030) records each video you surface via your YouTube search (the route inserts them idempotently). The Mine feed becomes 'your non-hidden subscriptions OR your search finds', and the Source filter now applies in Mine too: organic = subscriptions, search = your search finds, all = both (default stays organic, so the main feed is unchanged). The shared Library keeps using the global via_search flag. 2) Feed search ranks by relevance instead of a whole-phrase substring. A custom unaccent_simple text-search config + GIN index (migration 0031) back a YouTube-like fuzzy match: word-order-independent, multi-word AND, prefix on the word being typed, accent-insensitive. A new 'relevance' sort orders by ts_rank; the channel name still matches as a substring. The rank is scaled to an integer so the keyset cursor pages it exactly (a raw float4 breaks paging). _filtered_query returns the rank expr so only the feed list uses it.
This commit is contained in:
parent
a4abfa402f
commit
6cef826ecc
5 changed files with 208 additions and 22 deletions
|
|
@ -344,6 +344,25 @@ class VideoState(Base, UpdatedAtMixin):
|
|||
progress_updated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
||||
|
||||
|
||||
class SearchFind(Base, TimestampMixin):
|
||||
"""Per-user record of a video the user surfaced via their own live YouTube search.
|
||||
|
||||
Lets "videos I searched for" appear in that user's own (Mine) feed and the Mine Source
|
||||
filter — distinct from the GLOBAL `Video.via_search` provenance, which marks a video as
|
||||
search-discovered by *anyone* and drives the shared Library's Source filter."""
|
||||
|
||||
__tablename__ = "search_finds"
|
||||
__table_args__ = (UniqueConstraint("user_id", "video_id", name="uq_user_search_video"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("users.id", ondelete="CASCADE"), index=True
|
||||
)
|
||||
video_id: Mapped[str] = mapped_column(
|
||||
ForeignKey("videos.id", ondelete="CASCADE"), index=True
|
||||
)
|
||||
|
||||
|
||||
class ApiQuotaUsage(Base):
|
||||
"""Tracks YouTube Data API units spent per Pacific-time day (the quota resets at
|
||||
midnight Pacific). The whole app shares one daily budget."""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue