惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC
有赞技术团队
有赞技术团队
Vercel News
Vercel News
MongoDB | Blog
MongoDB | Blog
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
The Cloudflare Blog
B
Blog
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
U
Unit 42
D
Docker
月光博客
月光博客
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
A
About on SuperTechFans

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Building a Book Keyword Index with FTS5 Search, Auto-Sugg...
Manoir Yantai · 2026-06-27 · via DEV Community

Manoir Yantai

In knowledge management systems, text search is rarely sufficient—users expect instant suggestions and up-to-date indexes. Our book keyword index module leverages SQLite’s FTS5 for full-text search, implements auto-suggest through prefix queries, and runs a daily scan to keep the index fresh. Here’s how we built it without extra dependencies.

The core requirement was straightforward: index book keywords from a relational schema, support fast lookups, and return suggestions as the user types. FTS5, a virtual table module in SQLite, handles the heavy lifting. We create an FTS5 table mapped to the main keyword data, using content= to link it to an external table. This keeps the source data normalized while FTS5 manages the inverted index.

CREATE VIRTUAL TABLE keywords_fts USING fts5(
    keyword,
    book_id UNINDEXED,
    content=keywords,
    tokenize='unicode61 remove_diacritics 1'
);

The tokenize parameter strips accents and normalizes Unicode, which is critical for multilingual book metadata. For auto-suggest, we query FTS5 with a prefix operator. When a user types "neur", we append * to the search term. FTS5’s BM25 ranking returns top matches quickly, even for partial queries.

SELECT keyword, rank
FROM keywords_fts
WHERE keywords_fts MATCH 'neur*'
ORDER BY rank
LIMIT 10;

FTS5 prefix queries are efficient because they leverage the same inverted index. To avoid showing stale data, we restrict suggestions to keywords updated within the last 30 days, using a separate timestamp column in the source table. The query joins the FTS table with the source to filter by updated_at.

Daily scanning is the third piece. A scheduled background job (implemented via a simple cron entry or a scheduler like systemd timers) triggers rebuild_fts_index(). This function reads all keywords modified since the last scan, deletes stale rows from the FTS table using the content= sync, and inserts new ones. The key insight is to avoid a full rebuild—only delta syncs via the UPDATE and DELETE handlers that FTS5 provides when content= is set. The daily scan calls INSERT OR REPLACE on the source table to trigger these handlers automatically.

-- Example function called by daily cron
INSERT OR REPLACE INTO keywords (book_id, keyword, updated_at)
VALUES (?, ?, datetime('now'));
-- FTS5 automatically syncs because of content= link

We avoided external search engines (like Elasticsearch) to keep the stack simple and the dependency count low. For most book databases under a few million rows, FTS5 performs admirably. The auto-suggest latency stays under 10 ms, and the daily scan runs in seconds.

One caveat: FTS5 does not support incremental updates through the virtual table directly; it relies on triggers or the content= synchronization. Our daily scan ensures the updated_at field is set, and a trigger on the source table keeps FTS5 in sync for insertions and deletions. During the scan, we also rebuild the FTS index on the full table if corruption is detected, but this is rare.

The module integrates with the broader knowledge management system through a simple API: the search endpoint accepts a q parameter, the suggest endpoint returns a JSON array of completions, and the scan is invoked by an internal service. This design keeps the codebase modular and testable.

For experienced developers, the trade-offs are clear. FTS5 lacks distributed capabilities and advanced scoring, but for a single-machine setup with moderate data sizes, it’s a pragmatic choice. The auto-suggest prefix query requires a trailing wildcard, which can be customized with minimum token length filters to avoid empty results. Daily scanning uses a lock file to prevent concurrent runs, handled through a simple file-based mutex.

In production, the system handles thousands of queries per day without issues. The real lesson is that you don’t always need a heavyweight search infrastructure—sometimes a well-tuned FTS5 table and a daily cron job are enough. Focus on indexing the right fields, tuning the tokenizer for your dataset, and keeping the sync precise.