shared: sqlitesearch: Search trigram index too

Search the trigram index too, combining the results
with the results of the "normal" fts index.

Prioritize the latter since it makes more sense to
rank whole words higher.
This commit is contained in:
Albert S. 2022-10-18 16:06:08 +02:00
parent 583d5babf3
commit c155d25a37

View File

@ -141,9 +141,7 @@ QPair<QString, QVector<QString>> SqliteSearch::createSql(const Token &token)
} }
if(token.type == FILTER_CONTENT_CONTAINS) if(token.type == FILTER_CONTENT_CONTAINS)
{ {
return {" content.id IN (SELECT fts.ROWID FROM fts WHERE fts.content MATCH ? ORDER BY " return {" fts MATCH ? ", {escapeFtsArgument(value)}};
"rank) ",
{escapeFtsArgument(value)}};
} }
throw LooqsGeneralException("Unknown token passed (should not happen)"); throw LooqsGeneralException("Unknown token passed (should not happen)");
} }
@ -162,27 +160,15 @@ QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
bool ftsAlreadyJoined = false; bool ftsAlreadyJoined = false;
auto tokens = query.getTokens(); auto tokens = query.getTokens();
for(const Token &token : tokens) for(const Token &token : tokens)
{
if(token.type == FILTER_CONTENT_CONTAINS)
{
if(!ftsAlreadyJoined)
{
joinSql += " INNER JOIN fts ON content.ftsid = fts.ROWID ";
ftsAlreadyJoined = true;
}
whereSql += " fts.content MATCH ? ";
bindValues.append(escapeFtsArgument(token.value));
}
else
{ {
auto sql = createSql(token); auto sql = createSql(token);
whereSql += sql.first; whereSql += sql.first;
bindValues.append(sql.second); bindValues.append(sql.second);
} }
}
QString prepSql; QString prepSql;
QString sortSql = createSortSql(query.getSortConditions()); QString sortSql = createSortSql(query.getSortConditions());
int bindIterations = 1;
if(isContentSearch) if(isContentSearch)
{ {
if(sortSql.isEmpty()) if(sortSql.isEmpty())
@ -190,12 +176,24 @@ QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
if(std::find_if(tokens.begin(), tokens.end(), if(std::find_if(tokens.begin(), tokens.end(),
[](const Token &t) -> bool { return t.type == FILTER_CONTENT_CONTAINS; }) != tokens.end()) [](const Token &t) -> bool { return t.type == FILTER_CONTENT_CONTAINS; }) != tokens.end())
{ {
sortSql = "ORDER BY rank"; sortSql = "ORDER BY prio, rank";
} }
} }
prepSql = "SELECT file.path AS path, content.page AS page, file.mtime AS mtime, file.size AS size, " QString whereSqlTrigram = whereSql;
"file.filetype AS filetype FROM file INNER JOIN content ON file.id = content.fileid " + whereSqlTrigram.replace("fts MATCH", "fts_trigram MATCH"); // A bit dirty...
joinSql + " WHERE 1=1 AND " + whereSql + " " + sortSql; prepSql =
"SELECT DISTINCT path, page, mtime, size, filetype FROM ("
"SELECT file.path AS path, content.page AS page, file.mtime AS mtime, file.size AS size, "
"file.filetype AS filetype, 0 AS prio, fts.rank AS rank FROM file INNER JOIN content ON file.id = "
"content.fileid "
"INNER JOIN fts ON content.ftsid = fts.ROWID WHERE 1=1 AND " +
whereSql +
"UNION ALL SELECT file.path AS path, content.page AS page, file.mtime AS mtime, file.size AS size, "
"file.filetype AS filetype, 1 as prio, fts_trigram.rank AS rank FROM file INNER JOIN content ON file.id = "
"content.fileid " +
"INNER JOIN fts_trigram ON content.fts_trigramid = fts_trigram.ROWID WHERE 1=1 AND " + whereSqlTrigram +
" ) " + sortSql;
++bindIterations;
} }
else else
{ {
@ -215,6 +213,8 @@ QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
QSqlQuery dbquery(*db); QSqlQuery dbquery(*db);
dbquery.prepare(prepSql); dbquery.prepare(prepSql);
for(int i = 0; i < bindIterations; i++)
{
for(const QString &value : bindValues) for(const QString &value : bindValues)
{ {
if(value != "") if(value != "")
@ -222,6 +222,7 @@ QSqlQuery SqliteSearch::makeSqlQuery(const LooqsQuery &query)
dbquery.addBindValue(value); dbquery.addBindValue(value);
} }
} }
}
return dbquery; return dbquery;
} }