1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-12-18 14:10:30 +00:00

Enabled search for text based custom column content in simple search (fix for #2279)

This commit is contained in:
Ozzie Isaacs 2022-03-27 14:07:58 +02:00
parent 32a3c45ee0
commit 2f949ce1dd
4 changed files with 52 additions and 82 deletions

View File

@ -819,38 +819,21 @@ class CalibreDB:
def check_exists_book(self, authr, title): def check_exists_book(self, authr, title):
self.session.connection().connection.connection.create_function("lower", 1, lcase) self.session.connection().connection.connection.create_function("lower", 1, lcase)
q = list() q = list()
authorterms = re.split(r'\s*&\s*', authr) author_terms = re.split(r'\s*&\s*', authr)
for authorterm in authorterms: for author_term in author_terms:
q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%"))) q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + author_term + "%")))
return self.session.query(Books) \ return self.session.query(Books) \
.filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first() .filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first()
def search_query(self, term, config_read_column, *join): def search_query(self, term, config, *join):
term.strip().lower() term.strip().lower()
self.session.connection().connection.connection.create_function("lower", 1, lcase) self.session.connection().connection.connection.create_function("lower", 1, lcase)
q = list() q = list()
authorterms = re.split("[, ]+", term) author_terms = re.split("[, ]+", term)
for authorterm in authorterms: for author_term in author_terms:
q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%"))) q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + author_term + "%")))
query = self.generate_linked_query(config_read_column, Books) query = self.generate_linked_query(config.config_read_column, Books)
'''if not config_read_column:
query = (self.session.query(Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(Books)
.outerjoin(ub.ReadBook, and_(Books.id == ub.ReadBook.book_id,
int(current_user.id) == ub.ReadBook.user_id)))
else:
try:
read_column = cc_classes[config_read_column]
query = (self.session.query(Books, ub.ArchivedBook.is_archived, read_column.value)
.select_from(Books)
.outerjoin(read_column, read_column.book == Books.id))
except (KeyError, AttributeError, IndexError):
log.error("Custom Column No.{} is not existing in calibre database".format(config_read_column))
# Skip linking read column
query = self.session.query(Books, ub.ArchivedBook.is_archived, None)
query = query.outerjoin(ub.ArchivedBook, and_(Books.id == ub.ArchivedBook.book_id,
int(current_user.id) == ub.ArchivedBook.user_id))'''
if len(join) == 6: if len(join) == 6:
query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5]) query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5])
if len(join) == 3: if len(join) == 3:
@ -859,20 +842,42 @@ class CalibreDB:
query = query.outerjoin(join[0], join[1]) query = query.outerjoin(join[0], join[1])
elif len(join) == 1: elif len(join) == 1:
query = query.outerjoin(join[0]) query = query.outerjoin(join[0])
return query.filter(self.common_filters(True)).filter(
or_(Books.tags.any(func.lower(Tags.name).ilike("%" + term + "%")), cc = self.get_cc_columns(config, filter_config_custom_read=True)
Books.series.any(func.lower(Series.name).ilike("%" + term + "%")), filter_expression = [Books.tags.any(func.lower(Tags.name).ilike("%" + term + "%")),
Books.authors.any(and_(*q)), Books.series.any(func.lower(Series.name).ilike("%" + term + "%")),
Books.publishers.any(func.lower(Publishers.name).ilike("%" + term + "%")), Books.authors.any(and_(*q)),
func.lower(Books.title).ilike("%" + term + "%") Books.publishers.any(func.lower(Publishers.name).ilike("%" + term + "%")),
)) func.lower(Books.title).ilike("%" + term + "%")]
for c in cc:
if c.datatype not in ["datetime", "rating", "bool", "int", "float"]:
filter_expression.append(
getattr(Books,
'custom_column_' + str(c.id)).any(
func.lower(cc_classes[c.id].value).ilike("%" + term + "%")))
return query.filter(self.common_filters(True)).filter(or_(*filter_expression))
def get_cc_columns(self, config, filter_config_custom_read=False):
tmp_cc = self.session.query(CustomColumns).filter(CustomColumns.datatype.notin_(cc_exceptions)).all()
cc = []
r = None
if config.config_columns_to_ignore:
r = re.compile(config.config_columns_to_ignore)
for col in tmp_cc:
if filter_config_custom_read and config.config_read_column and config.config_read_column == col.id:
continue
if r and r.match(col.name):
continue
cc.append(col)
return cc
# read search results from calibre-database and return it (function is used for feed and simple search # read search results from calibre-database and return it (function is used for feed and simple search
def get_search_results(self, term, offset=None, order=None, limit=None, def get_search_results(self, term, config, offset=None, order=None, limit=None, *join):
config_read_column=False, *join):
order = order[0] if order else [Books.sort] order = order[0] if order else [Books.sort]
pagination = None pagination = None
result = self.search_query(term, config_read_column, *join).order_by(*order).all() result = self.search_query(term, config, *join).order_by(*order).all()
result_count = len(result) result_count = len(result)
if offset != None and limit != None: if offset != None and limit != None:
offset = int(offset) offset = int(offset)

View File

@ -953,24 +953,6 @@ def check_valid_domain(domain_text):
return not len(result) return not len(result)
def get_cc_columns(filter_config_custom_read=False):
tmpcc = calibre_db.session.query(db.CustomColumns)\
.filter(db.CustomColumns.datatype.notin_(db.cc_exceptions)).all()
cc = []
r = None
if config.config_columns_to_ignore:
r = re.compile(config.config_columns_to_ignore)
for col in tmpcc:
if filter_config_custom_read and config.config_read_column and config.config_read_column == col.id:
continue
if r and r.match(col.name):
continue
cc.append(col)
return cc
def get_download_link(book_id, book_format, client): def get_download_link(book_id, book_format, client):
book_format = book_format.split(".")[0] book_format = book_format.split(".")[0]
book = calibre_db.get_filtered_book(book_id, allow_show_archived=True) book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)

View File

@ -467,7 +467,7 @@ def feed_unread_books():
def feed_search(term): def feed_search(term):
if term: if term:
entries, __, ___ = calibre_db.get_search_results(term, config_read_column=config.config_read_column) entries, __, ___ = calibre_db.get_search_results(term, config=config)
entries_count = len(entries) if len(entries) > 0 else 1 entries_count = len(entries) if len(entries) > 0 else 1
pagination = Pagination(1, entries_count, entries_count) pagination = Pagination(1, entries_count, entries_count)
return render_xml_template('feed.xml', searchterm=term, entries=entries, pagination=pagination) return render_xml_template('feed.xml', searchterm=term, entries=entries, pagination=pagination)

View File

@ -50,7 +50,7 @@ from . import babel, db, ub, config, get_locale, app
from . import calibre_db, kobo_sync_status from . import calibre_db, kobo_sync_status
from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download from .gdriveutils import getFileFromEbooksFolder, do_gdrive_download
from .helper import check_valid_domain, render_task_status, check_email, check_username, \ from .helper import check_valid_domain, render_task_status, check_email, check_username, \
get_cc_columns, get_book_cover, get_download_link, send_mail, generate_random_password, \ get_book_cover, get_download_link, send_mail, generate_random_password, \
send_registration_mail, check_send_to_kindle, check_read_formats, tags_filters, reset_password, valid_email, \ send_registration_mail, check_send_to_kindle, check_read_formats, tags_filters, reset_password, valid_email, \
edit_book_read_status edit_book_read_status
from .pagination import Pagination from .pagination import Pagination
@ -724,10 +724,10 @@ def render_prepare_search_form(cc):
def render_search_results(term, offset=None, order=None, limit=None): def render_search_results(term, offset=None, order=None, limit=None):
join = db.books_series_link, db.books_series_link.c.book == db.Books.id, db.Series join = db.books_series_link, db.books_series_link.c.book == db.Books.id, db.Series
entries, result_count, pagination = calibre_db.get_search_results(term, entries, result_count, pagination = calibre_db.get_search_results(term,
config,
offset, offset,
order, order,
limit, limit,
config.config_read_column,
*join) *join)
return render_title_template('search.html', return render_title_template('search.html',
searchterm=term, searchterm=term,
@ -765,7 +765,7 @@ def books_list(data, sort_param, book_id, page):
@login_required @login_required
def books_table(): def books_table():
visibility = current_user.view_settings.get('table', {}) visibility = current_user.view_settings.get('table', {})
cc = get_cc_columns(filter_config_custom_read=True) cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True)
return render_title_template('book_table.html', title=_(u"Books List"), cc=cc, page="book_table", return render_title_template('book_table.html', title=_(u"Books List"), cc=cc, page="book_table",
visiblility=visibility) visiblility=visibility)
@ -809,7 +809,7 @@ def list_books():
calibre_db.common_filters(allow_show_archived=True)).count() calibre_db.common_filters(allow_show_archived=True)).count()
if state is not None: if state is not None:
if search_param: if search_param:
books = calibre_db.search_query(search_param, config.config_read_column).all() books = calibre_db.search_query(search_param, config).all()
filtered_count = len(books) filtered_count = len(books)
else: else:
query = calibre_db.generate_linked_query(config.config_read_column, db.Books) query = calibre_db.generate_linked_query(config.config_read_column, db.Books)
@ -817,10 +817,10 @@ def list_books():
entries = calibre_db.get_checkbox_sorted(books, state, off, limit, order, True) entries = calibre_db.get_checkbox_sorted(books, state, off, limit, order, True)
elif search_param: elif search_param:
entries, filtered_count, __ = calibre_db.get_search_results(search_param, entries, filtered_count, __ = calibre_db.get_search_results(search_param,
config,
off, off,
[order, ''], [order, ''],
limit, limit,
config.config_read_column,
*join) *join)
else: else:
entries, __, __ = calibre_db.fill_indexpage_with_archived_books((int(off) / (int(limit)) + 1), entries, __, __ = calibre_db.fill_indexpage_with_archived_books((int(off) / (int(limit)) + 1),
@ -1232,26 +1232,9 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
sort_param = order[0] if order else [db.Books.sort] sort_param = order[0] if order else [db.Books.sort]
pagination = None pagination = None
cc = get_cc_columns(filter_config_custom_read=True) cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True)
calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase) calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase)
query = calibre_db.generate_linked_query(config.config_read_column, db.Books) query = calibre_db.generate_linked_query(config.config_read_column, db.Books)
'''if not config.config_read_column:
query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, ub.ReadBook).select_from(db.Books)
.outerjoin(ub.ReadBook, and_(db.Books.id == ub.ReadBook.book_id,
int(current_user.id) == ub.ReadBook.user_id)))
else:
try:
read_column = db.cc_classes[config.config_read_column]
query = (calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, read_column.value)
.select_from(db.Books)
.outerjoin(read_column, read_column.book == db.Books.id))
except (KeyError, AttributeError, IndexError):
log.error("Custom Column No.{} is not existing in calibre database".format(config.config_read_column))
# Skip linking read column
query = calibre_db.session.query(db.Books, ub.ArchivedBook.is_archived, None)
query = query.outerjoin(ub.ArchivedBook, and_(db.Books.id == ub.ArchivedBook.book_id,
int(current_user.id) == ub.ArchivedBook.user_id))'''
q = query.outerjoin(db.books_series_link, db.books_series_link.c.book == db.Books.id) \ q = query.outerjoin(db.books_series_link, db.books_series_link.c.book == db.Books.id) \
.outerjoin(db.Series) \ .outerjoin(db.Series) \
.filter(calibre_db.common_filters(True)) .filter(calibre_db.common_filters(True))
@ -1338,7 +1321,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
if description: if description:
q = q.filter(db.Books.comments.any(func.lower(db.Comments.text).ilike("%" + description + "%"))) q = q.filter(db.Books.comments.any(func.lower(db.Comments.text).ilike("%" + description + "%")))
# search custom culumns # search custom columns
try: try:
q = adv_search_custom_columns(cc, term, q) q = adv_search_custom_columns(cc, term, q)
except AttributeError as ex: except AttributeError as ex:
@ -1370,7 +1353,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
@login_required_if_no_ano @login_required_if_no_ano
def advanced_search_form(): def advanced_search_form():
# Build custom columns names # Build custom columns names
cc = get_cc_columns(filter_config_custom_read=True) cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True)
return render_prepare_search_form(cc) return render_prepare_search_form(cc)
@ -1757,10 +1740,10 @@ def show_book(book_id):
for lang_index in range(0, len(entry.languages)): for lang_index in range(0, len(entry.languages)):
entry.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), entry.languages[ entry.languages[lang_index].language_name = isoLanguages.get_language_name(get_locale(), entry.languages[
lang_index].lang_code) lang_index].lang_code)
cc = get_cc_columns(filter_config_custom_read=True) cc = calibre_db.get_cc_columns(config, filter_config_custom_read=True)
book_in_shelves = [] book_in_shelves = []
shelfs = ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).all() shelves = ub.session.query(ub.BookShelf).filter(ub.BookShelf.book_id == book_id).all()
for sh in shelfs: for sh in shelves:
book_in_shelves.append(sh.shelf) book_in_shelves.append(sh.shelf)
entry.tags = sort(entry.tags, key=lambda tag: tag.name) entry.tags = sort(entry.tags, key=lambda tag: tag.name)