I have two tables:
personspersons_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
rankfunction does in the comments above the query it is used in:rankis expected to be a user supplied function. It does not ship with SQLite.Here's an implementation of the
rankfunction in Kotlin which calculates the relevance score on the basis of the data supplied bymatchinfousing the default "pcx" argument:To understand how this code works, you should go through the
rankfuncexample 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
matchinfoblob from the database, and then pass it to our rank function.Here's an example on how to do it with Room:
The retrieved
ByteArraycontains 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: