I have two tables:
persons
persons_fts
.
Here are the definitions of the tables:
CREATE TABLE persons(name TEXT PRIMARY KEY NOT NULL, details TEXT);
CREATE VIRTUAL TABLE persons_fts USING FTS4(name TEXT NOT NULL, details TEXT, context=persons);
I want to do a full-text-search with a query on the persons_fts
table, and rank the results on the basis of relevance. After looking at the official docs on how to do this, I ended with the following query:
SELECT *
FROM persons
JOIN persons_fts ON persons.name = persons_fts.name
WHERE persons_fts MATCH :query
ORDER BY rank(matchinfo(persons_fts)) DESC;
Besides the extra join, this query is the exact same as the one outlined in the official docs. However, I get an error when I try to execute it:
Error retrieving data from the table: Wrong number of arguments to function rank() (code 1 SQLITE_ERROR)
What am I doing wrong?
Please note that using FTS5 is not an option for me.
The linked SQLite documentation in the question clarifies what the
rank
function does in the comments above the query it is used in:rank
is expected to be a user supplied function. It does not ship with SQLite.Here's an implementation of the
rank
function in Kotlin which calculates the relevance score on the basis of the data supplied bymatchinfo
using the default "pcx" argument:To understand how this code works, you should go through the
rankfunc
example given in the official docs.Since our rank function is a Kotlin function, it can not be used directly by SQLite. Instead, we will need to first retrieve the
matchinfo
blob from the database, and then pass it to our rank function.Here's an example on how to do it with Room:
The retrieved
ByteArray
contains a sequence of numbers representing the match info, in which each number is represented by 4 bytes. The first byte is the actual value, and the next three bytes are zero. Therefore we need to remove the redundant zeroes before passing this ByteArray torank
. This can be done with a simple method:This setup can be used like this: