Allow FTS searches to not return text

Allows efficiently querying for which books match without th eoverhead
of converting the book text to a python string
This commit is contained in:
Kovid Goyal 2022-05-05 12:39:18 +05:30
parent 0a6dc87fcd
commit cac2a91df9
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -137,31 +137,36 @@ class FTS:
def search(self, def search(self,
fts_engine_query, use_stemming, highlight_start, highlight_end, snippet_size, restrict_to_book_ids, fts_engine_query, use_stemming, highlight_start, highlight_end, snippet_size, restrict_to_book_ids,
return_text=True,
): ):
fts_engine_query = unicode_normalize(fts_engine_query) fts_engine_query = unicode_normalize(fts_engine_query)
fts_table = 'books_fts' + ('_stemmed' if use_stemming else '') fts_table = 'books_fts' + ('_stemmed' if use_stemming else '')
text = 'books_text.searchable_text' if return_text:
if highlight_start is not None and highlight_end is not None: text = 'books_text.searchable_text'
if snippet_size is not None: if highlight_start is not None and highlight_end is not None:
text = f'snippet("{fts_table}", 0, "{highlight_start}", "{highlight_end}", "", {max(1, min(snippet_size, 64))})' if snippet_size is not None:
else: text = f'snippet("{fts_table}", 0, "{highlight_start}", "{highlight_end}", "", {max(1, min(snippet_size, 64))})'
text = f'highlight("{fts_table}", 0, "{highlight_start}", "{highlight_end}")' else:
query = 'SELECT {0}.id, {0}.book, {0}.format, {1} FROM {0} ' text = f'highlight("{fts_table}", 0, "{highlight_start}", "{highlight_end}")'
query = query.format('books_text', text) text = ', ' + text
else:
text = ''
query = 'SELECT {0}.id, {0}.book, {0}.format {1} FROM {0} '.format('books_text', text)
query += f' JOIN {fts_table} ON fts_db.books_text.id = {fts_table}.rowid' query += f' JOIN {fts_table} ON fts_db.books_text.id = {fts_table}.rowid'
query += f' WHERE "{fts_table}" MATCH ?' query += f' WHERE "{fts_table}" MATCH ?'
data = [fts_engine_query] data = [fts_engine_query]
query += f' ORDER BY {fts_table}.rank ' query += f' ORDER BY {fts_table}.rank '
conn = self.get_connection() conn = self.get_connection()
try: try:
for (rowid, book_id, fmt, text) in conn.execute(query, tuple(data)): for record in conn.execute(query, tuple(data)):
book_id = record[1]
if restrict_to_book_ids is not None and book_id not in restrict_to_book_ids: if restrict_to_book_ids is not None and book_id not in restrict_to_book_ids:
continue continue
yield { yield {
'id': rowid, 'id': record[0],
'book_id': book_id, 'book_id': book_id,
'format': fmt, 'format': record[2],
'text': text, 'text': record[3] if return_text else '',
} }
except apsw.SQLError as e: except apsw.SQLError as e:
raise FTSQueryError(fts_engine_query, query, e) from e raise FTSQueryError(fts_engine_query, query, e) from e