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

推荐订阅源

量子位
Recent Announcements
Recent Announcements
D
Docker
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
The GitHub Blog
The GitHub Blog
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
腾讯CDC
B
Blog
博客园_首页
罗磊的独立博客
D
DataBreaches.Net
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LangChain Blog
aimingoo的专栏
aimingoo的专栏
MongoDB | Blog
MongoDB | Blog
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence

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.