Skip to content

Instantly share code, notes, and snippets.

@pallocchi
Last active August 3, 2018 00:26
Show Gist options
  • Save pallocchi/090da8ce3d2c9a7c1d556700d8f774b1 to your computer and use it in GitHub Desktop.
Save pallocchi/090da8ce3d2c9a7c1d556700d8f774b1 to your computer and use it in GitHub Desktop.
Offline full-text search in Android & iOS
func search(text: String) -> [Movie] {
var movies: [Movie] = []
var statement: OpaquePointer?
let query = "SELECT title, overview, poster, year, matchinfo(movies, 'pcnalx') FROM movies WHERE movies MATCH '\(text)*'"
if sqlite3_prepare_v2(db, query, -1, &statement, nil) != SQLITE_OK {
print("Error preparing select: \(String(cString: sqlite3_errmsg(db)!))")
}
while sqlite3_step(statement) == SQLITE_ROW {
if
let cTitle = sqlite3_column_text(statement, 0),
let cOverview = sqlite3_column_text(statement, 1),
let cPoster = sqlite3_column_text(statement, 2)
{
let cYear = sqlite3_column_int64(statement, 3)
// Read and prepare matchinfo blob
let buf = sqlite3_column_blob(statement, 4).assumingMemoryBound(to: UInt32.self)
let blob = [UInt32](UnsafeBufferPointer(start: buf, count: Int(sqlite3_column_bytes(statement, 4))))
// Calculate score based on matchinfo values
// Here I'm only using the first column (title) to calculate the score
let score = OkapiBM25.score(matchinfo: blob, column: 0)
movies.append(
Movie(
title: String(cString: cTitle),
overview: String(cString: cOverview),
poster: String(cString: cPoster),
year: Int(cYear),
score: score
)
)
}
}
if sqlite3_finalize(statement) != SQLITE_OK {
print("Error finalizing prepared statement: \(String(cString: sqlite3_errmsg(db)!))")
}
// Sort the movies by the Okapi BM25 score
return movies.sorted(by: {$0.score > $1.score})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment