mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow searching for books by id and uuid using the id: and uuid: prefixes
Also create a nicer API for refreshing the set of search prefixes
This commit is contained in:
parent
4a56a211fe
commit
68f20774fc
@ -157,7 +157,7 @@ class Cache(object):
|
|||||||
self.field_metadata.add_grouped_search_terms(
|
self.field_metadata.add_grouped_search_terms(
|
||||||
self._pref('grouped_search_terms', {}))
|
self._pref('grouped_search_terms', {}))
|
||||||
|
|
||||||
self._search_api.change_locations(self.field_metadata.get_search_terms())
|
self._refresh_search_locations()
|
||||||
|
|
||||||
self.dirtied_cache = {x:i for i, (x,) in enumerate(
|
self.dirtied_cache = {x:i for i, (x,) in enumerate(
|
||||||
self.backend.execute('SELECT book FROM metadata_dirtied'))}
|
self.backend.execute('SELECT book FROM metadata_dirtied'))}
|
||||||
@ -1758,6 +1758,10 @@ class Cache(object):
|
|||||||
def change_search_locations(self, newlocs):
|
def change_search_locations(self, newlocs):
|
||||||
self._search_api.change_locations(newlocs)
|
self._search_api.change_locations(newlocs)
|
||||||
|
|
||||||
|
@write_api
|
||||||
|
def refresh_search_locations(self):
|
||||||
|
self._search_api.change_locations(self.field_metadata.get_search_terms())
|
||||||
|
|
||||||
@write_api
|
@write_api
|
||||||
def dump_and_restore(self, callback=None, sql=None):
|
def dump_and_restore(self, callback=None, sql=None):
|
||||||
return self.backend.dump_and_restore(callback=callback, sql=sql)
|
return self.backend.dump_and_restore(callback=callback, sql=sql)
|
||||||
|
@ -562,10 +562,16 @@ class Parser(SearchQueryParser): # {{{
|
|||||||
if (dt in ('rating', 'int', 'float') or
|
if (dt in ('rating', 'int', 'float') or
|
||||||
(dt == 'composite' and
|
(dt == 'composite' and
|
||||||
fm['display'].get('composite_sort', '') == 'number')):
|
fm['display'].get('composite_sort', '') == 'number')):
|
||||||
field = self.dbcache.fields[location]
|
if location == 'id':
|
||||||
|
is_many = False
|
||||||
|
def fi(default_value=None):
|
||||||
|
for qid in candidates:
|
||||||
|
yield qid, {qid}
|
||||||
|
else:
|
||||||
|
field = self.dbcache.fields[location]
|
||||||
|
fi, is_many = partial(self.field_iter, location, candidates), field.is_many
|
||||||
return self.num_search(
|
return self.num_search(
|
||||||
icu_lower(query), partial(self.field_iter, location, candidates),
|
icu_lower(query), fi, location, dt, candidates, is_many=is_many)
|
||||||
location, dt, candidates, is_many=field.is_many)
|
|
||||||
|
|
||||||
# take care of the 'count' operator for is_multiples
|
# take care of the 'count' operator for is_multiples
|
||||||
if (fm['is_multiple'] and
|
if (fm['is_multiple'] and
|
||||||
@ -602,8 +608,8 @@ class Parser(SearchQueryParser): # {{{
|
|||||||
for x, fm in self.field_metadata.iteritems():
|
for x, fm in self.field_metadata.iteritems():
|
||||||
if x.startswith('@'):
|
if x.startswith('@'):
|
||||||
continue
|
continue
|
||||||
if fm['search_terms'] and x != 'series_sort':
|
if fm['search_terms'] and x not in {'series_sort', 'id'}:
|
||||||
if x not in self.virtual_fields:
|
if x not in self.virtual_fields and x != 'uuid':
|
||||||
# We dont search virtual fields because if we do, search
|
# We dont search virtual fields because if we do, search
|
||||||
# caching will not be used
|
# caching will not be used
|
||||||
all_locs.add(x)
|
all_locs.add(x)
|
||||||
|
@ -274,7 +274,7 @@ class ReadingTest(BaseTest):
|
|||||||
'rating:false', 'rating:>4', 'tags:#<2', 'tags:#>7',
|
'rating:false', 'rating:>4', 'tags:#<2', 'tags:#>7',
|
||||||
'cover:false', 'cover:true', '#float:>11', '#float:<1k',
|
'cover:false', 'cover:true', '#float:>11', '#float:<1k',
|
||||||
'#float:10.01', '#float:false', 'series_index:1',
|
'#float:10.01', '#float:false', 'series_index:1',
|
||||||
'series_index:<3', 'id:1', 'id:>2',
|
'series_index:<3',
|
||||||
|
|
||||||
# Bool tests
|
# Bool tests
|
||||||
'#yesno:true', '#yesno:false', '#yesno:yes', '#yesno:no',
|
'#yesno:true', '#yesno:false', '#yesno:yes', '#yesno:no',
|
||||||
@ -289,7 +289,7 @@ class ReadingTest(BaseTest):
|
|||||||
# Text tests
|
# Text tests
|
||||||
'title:="Title One"', 'title:~title', '#enum:=one', '#enum:tw',
|
'title:="Title One"', 'title:~title', '#enum:=one', '#enum:tw',
|
||||||
'#enum:false', '#enum:true', 'series:one', 'tags:one', 'tags:true',
|
'#enum:false', '#enum:true', 'series:one', 'tags:one', 'tags:true',
|
||||||
'tags:false', '2', 'one', '20.02', '"publisher one"',
|
'tags:false', 'uuid:2', 'one', '20.02', '"publisher one"',
|
||||||
'"my comments one"',
|
'"my comments one"',
|
||||||
|
|
||||||
# User categories
|
# User categories
|
||||||
@ -312,6 +312,13 @@ class ReadingTest(BaseTest):
|
|||||||
'Old result: %r != New result: %r for search: %s'%(
|
'Old result: %r != New result: %r for search: %s'%(
|
||||||
ans, nr, query))
|
ans, nr, query))
|
||||||
|
|
||||||
|
# Test searching by id, which was introduced in the new backend
|
||||||
|
self.assertEqual(cache.search('id:1', ''), {1})
|
||||||
|
self.assertEqual(cache.search('id:>1', ''), {2, 3})
|
||||||
|
|
||||||
|
# Note that the old db searched uuid for un-prefixed searches, the new
|
||||||
|
# db does not, for performance
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def test_get_categories(self): # {{{
|
def test_get_categories(self): # {{{
|
||||||
|
@ -876,7 +876,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
tb_cats.add_user_category(label=u'@' + cat, name=cat)
|
tb_cats.add_user_category(label=u'@' + cat, name=cat)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.db.data.change_search_locations(self.db.field_metadata.get_search_terms())
|
self.db.new_api.refresh_search_locations()
|
||||||
|
|
||||||
if len(self.db.saved_search_names()):
|
if len(self.db.saved_search_names()):
|
||||||
tb_cats.add_search_category(label='search', name=_('Searches'))
|
tb_cats.add_search_category(label='search', name=_('Searches'))
|
||||||
|
@ -111,7 +111,7 @@ class TagBrowserMixin(object): # {{{
|
|||||||
db.field_metadata.remove_user_categories()
|
db.field_metadata.remove_user_categories()
|
||||||
for k in d.categories:
|
for k in d.categories:
|
||||||
db.field_metadata.add_user_category('@' + k, k)
|
db.field_metadata.add_user_category('@' + k, k)
|
||||||
db.data.change_search_locations(db.field_metadata.get_search_terms())
|
db.new_api.refresh_search_locations()
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
|
|
||||||
def do_delete_user_category(self, category_name):
|
def do_delete_user_category(self, category_name):
|
||||||
|
@ -209,7 +209,7 @@ def _builtin_field_metadata():
|
|||||||
'is_multiple':{},
|
'is_multiple':{},
|
||||||
'kind':'field',
|
'kind':'field',
|
||||||
'name':None,
|
'name':None,
|
||||||
'search_terms':[],
|
'search_terms':['id'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False,
|
'is_category':False,
|
||||||
'is_csp': False}),
|
'is_csp': False}),
|
||||||
@ -329,7 +329,7 @@ def _builtin_field_metadata():
|
|||||||
'is_multiple':{},
|
'is_multiple':{},
|
||||||
'kind':'field',
|
'kind':'field',
|
||||||
'name':None,
|
'name':None,
|
||||||
'search_terms':[],
|
'search_terms':['uuid'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False,
|
'is_category':False,
|
||||||
'is_csp': False}),
|
'is_csp': False}),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user