I'm working on a poor, but ok for us, full-text search using only PSQL in Firebird. I'll try to simplify as much as possible by focusing on my problem:
Summing up, this a dictionary table:
SELECT * FROM FTS_KEYWORDS
ID | KEYWORD
----+-----------
1 | 'FORD'
1 | 'MUSTANG'
1 | '2010'
2 | 'FORD'
2 | 'FUSION'
2 | 'TURBO'
2 | '2010'
3 | 'FORD'
3 | 'RANGER'
3 | 'TURBO'
3 | '2010'
3 | 'BLACK'
There is too a FTS_TOKENIZE()
procedure to get the words from the whole strings
Case 1: User search with 1 keyword
SELECT TOKENS FROM FTS_TOKENIZE('FORD')
TOKENS
-------------
'FORD'
This would then be the SQL required to get the correct results:
:TOKEN_1 = 'FORD'
SELECT DISTINCT ID
FROM FTS_KEYWORDS
WHERE (KEYWORD STARTING :TOKEN_1)
ID
-----
1
2
3
Case 2: User search with 3 keywords
SELECT TOKENS FROM FTS_TOKENIZE('FORD 2010 BLACK')
TOKENS
-------------
'FORD'
'2010'
'BLACK'
So, SQL to retrieve the correct values:
:TOKEN_1 = 'FORD'
:TOKEN_2 = '2010'
:TOKEN_3 = 'BLACK'
SELECT DISTINCT K1.ID
FROM FTS_KEYWORDS K1
WHERE (K1.KEYWORD STARTING :TOKEN_1)
AND (K1.ID IN (SELECT DISTINCT K2.ID
FROM FTS_KEYWORDS K2
WHERE (K2.KEYWORD STARTING :TOKEN_2)))
AND (K2.ID IN (SELECT DISTINCT K3.ID
FROM FTS_KEYWORDS K3
WHERE (K3.KEYWORD STARTING :TOKEN_3)))
ID
-----
3
ID 3
is the only ID
that has all the keywords matching the search.
The SQL to retrieve values is a recursive nested by the tokens amount user query search.
Currently, in a procedure FTS_SEARCH()
, I build a SQL string and use then in an EXECUTE STATEMENT
way, but I do not think this is ideal.
I think this can be done with recursive Common Table Expressions (“WITH ... AS ... SELECT”), but I was not able to do it, because, based on the current examples available, it requires a table with Parent_ID
and does not accept input parameters, which is not my case.
My question is: Is there a way to do this search in a recursive way using CTE or other SQL trick?