Full-Text Search

SQLite.swift provides support for SQLite's powerful full-text search (FTS) capabilities. FTS allows you to perform fast, sophisticated searches on text content stored in your database.

To use FTS, you create a VirtualTable.

FTS5

FTS5 is the latest generation of full-text search in SQLite and is recommended for new projects. Note that it may require a newer version of SQLite than is provided by the OS; see the Installation guide for how to use a standalone version.

Creating an FTS5 Table

You define an FTS5 table by creating a VirtualTable and configuring it with an FTS5Config object.

let emails = VirtualTable("emails")
let subject = Expression<String>("subject")
let body = Expression<String>("body")

let config = FTS5Config()
    .column(subject)
    .column(body, [.unindexed]) // You can mark columns as unindexed

// Create the virtual table
try db.run(emails.create(.FTS5(config)))
// CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)

Searching with FTS5

Use the match method to perform a search. FTS5 has a rich query syntax.

try db.run(emails.insert(
    subject <- "New Swift Release",
    body <- "Swift 5.7 has been released with powerful new features."
))

// Find all documents containing "swift"
let results = try db.prepare(emails.match("swift"))

// FTS5 syntax can target specific columns
let subjectResults = try db.prepare(emails.match("subject:swift"))

FTS4

FTS4 is the older but still widely-supported version of full-text search.

Creating an FTS4 Table

The setup is similar to FTS5, but uses an FTS4Config.

let documents = VirtualTable("documents")
let title = Expression<String>("title")
let content = Expression<String>("content")

let config = FTS4Config()
    .column(title)
    .column(content)
    .tokenizer(.Porter) // FTS4 supports different tokenizers

try db.run(documents.create(.FTS4(config)))
// CREATE VIRTUAL TABLE "documents" USING fts4("title", "content", tokenize=porter)

Searching with FTS4

Searching with FTS4 also uses the match method. The query syntax is different from FTS5.

try db.run(documents.insert(
    title <- "Learning Swift",
    content <- "This is a book about the Swift programming language."
))

// Find all documents containing "swift" or "language"
let results = try db.prepare(documents.match("swift OR language"))

for doc in results {
    print(doc[title]) // "Learning Swift"
}