SQLite User Forum

FTS5 ranking
Login

FTS5 ranking

(1) By istibekesi on 2023-11-16 12:40:24 [source]

I would like to find a way to specify a custom FTS5 rankingin such a way that empty values receive a higher rank. It would be easier to explain the question through the following setup.

sqlite> CREATE TABLE locations(rowid INTEGER PRIMARY KEY, country TEXT NOT NULL, city TEXT NOT NULL);
sqlite> 
sqlite> INSERT INTO locations (country, city) VALUES ("Mexico", "Mexico City");
sqlite> INSERT INTO locations (country, city) VALUES ("Mexico", "Cancun");
sqlite> INSERT INTO locations (country, city) VALUES ("Mexico", "Acapulco");
sqlite> INSERT INTO locations (country, city) VALUES ("Mexico", "");
sqlite> 
sqlite> CREATE VIRTUAL TABLE locations_search USING fts5(country, city, content='locations', prefix='3 4 5');
sqlite> INSERT INTO locations_search(locations_search, rank) VALUES('rank', 'bm25(1.0, 2.0)');
sqlite> INSERT INTO locations_search(rowid, country, city) SELECT rowid, country, city FROM locations;

Now if I perform the following query, the result looks something like this:

sqlite> SELECT country, city, rank FROM locations_search WHERE locations_search MATCH 'Mex*' ORDER BY rank;
Mexico|Mexico City|-1.52475247524752e-06
Mexico||-1.21259842519685e-06
Mexico|Cancun|-9.4478527607362e-07
Mexico|Acapulco|-9.4478527607362e-07

How can I write a query that ranks the second result higher, so country "Mexico" without a city should be the top ranked result, followed by "Mexico, Mexico City"?

(2) By jose isaias cabrera (jicman) on 2023-11-16 14:30:21 in reply to 1 [link] [source]

It's probably not what you want, but will you try this,

SELECT country, city, rank FROM locations_search WHERE locations_search MATCH 'Mex*' ORDER BY city,rank ASC;

This will bring any empty city values first, and then sort by rank in an ascending order. Something to think about.

(3) By jose isaias cabrera (jicman) on 2023-11-16 15:36:25 in reply to 1 [link] [source]

This is something that Keith taught me once,

SELECT country, city, rank FROM locations_search WHERE locations_search MATCH 'Mex*' ORDER BY 
CASE WHEN city = '' OR city is NULL THEN 1 ELSE 2 END, rank
;

This one should work better.

(4) By anonymous on 2023-11-20 15:03:46 in reply to 3 [link] [source]

I do not know who Keith is, but this second solution is awesome and gives exactly the same result as I wanted to achieve!

I was focusing so much on the fts MATCH clause that I did not even think about such a tricky ORDER BY.

It saved the day, thanks a lot 🙌