mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Searching on identifiers
This commit is contained in:
commit
2a3f412b48
@ -66,7 +66,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
choices = set([k for k in db.field_metadata.all_field_keys()
|
choices = set([k for k in db.field_metadata.all_field_keys()
|
||||||
if db.field_metadata[k]['is_category'] and
|
if db.field_metadata[k]['is_category'] and
|
||||||
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']])
|
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']])
|
||||||
choices -= set(['authors', 'publisher', 'formats', 'news'])
|
choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
|
||||||
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
||||||
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
||||||
choices=sorted(list(choices), key=sort_key))
|
choices=sorted(list(choices), key=sort_key))
|
||||||
|
@ -418,9 +418,9 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
return matches
|
return matches
|
||||||
|
|
||||||
def get_user_category_matches(self, location, query, candidates):
|
def get_user_category_matches(self, location, query, candidates):
|
||||||
res = set([])
|
matches = set([])
|
||||||
if self.db_prefs is None or len(query) < 2:
|
if self.db_prefs is None or len(query) < 2:
|
||||||
return res
|
return matches
|
||||||
user_cats = self.db_prefs.get('user_categories', [])
|
user_cats = self.db_prefs.get('user_categories', [])
|
||||||
c = set(candidates)
|
c = set(candidates)
|
||||||
|
|
||||||
@ -435,10 +435,56 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
for (item, category, ign) in user_cats[key]:
|
for (item, category, ign) in user_cats[key]:
|
||||||
s = self.get_matches(category, '=' + item, candidates=c)
|
s = self.get_matches(category, '=' + item, candidates=c)
|
||||||
c -= s
|
c -= s
|
||||||
res |= s
|
matches |= s
|
||||||
if query == 'false':
|
if query == 'false':
|
||||||
return candidates - res
|
return candidates - matches
|
||||||
return res
|
return matches
|
||||||
|
|
||||||
|
def get_keypair_matches(self, location, query, candidates):
|
||||||
|
matches = set([])
|
||||||
|
if query.find(':') >= 0:
|
||||||
|
q = [q.strip() for q in query.split(':')]
|
||||||
|
if len(q) != 2:
|
||||||
|
raise ParseException(query, len(query),
|
||||||
|
'Invalid query format for colon-separated search', self)
|
||||||
|
(keyq, valq) = q
|
||||||
|
keyq_mkind, keyq = self._matchkind(keyq)
|
||||||
|
valq_mkind, valq = self._matchkind(valq)
|
||||||
|
else:
|
||||||
|
keyq = keyq_mkind = ''
|
||||||
|
valq_mkind, valq = self._matchkind(query)
|
||||||
|
|
||||||
|
loc = self.field_metadata[location]['rec_index']
|
||||||
|
for id_ in candidates:
|
||||||
|
item = self._data[id_]
|
||||||
|
if item is None or item[loc] is None:
|
||||||
|
continue
|
||||||
|
pairs = [p.strip() for p in item[loc].split(',')]
|
||||||
|
for pair in pairs:
|
||||||
|
parts = pair.split(':')
|
||||||
|
if len(parts) != 2:
|
||||||
|
continue
|
||||||
|
k = parts[:1]
|
||||||
|
v = parts[1:]
|
||||||
|
if keyq and not _match(keyq, k, keyq_mkind):
|
||||||
|
continue
|
||||||
|
if valq and not _match(valq, v, valq_mkind):
|
||||||
|
continue
|
||||||
|
matches.add(id_)
|
||||||
|
return matches
|
||||||
|
|
||||||
|
def _matchkind(self, query):
|
||||||
|
matchkind = CONTAINS_MATCH
|
||||||
|
if (len(query) > 1):
|
||||||
|
if query.startswith('\\'):
|
||||||
|
query = query[1:]
|
||||||
|
elif query.startswith('='):
|
||||||
|
matchkind = EQUALS_MATCH
|
||||||
|
query = query[1:]
|
||||||
|
elif query.startswith('~'):
|
||||||
|
matchkind = REGEXP_MATCH
|
||||||
|
query = query[1:]
|
||||||
|
return matchkind, query
|
||||||
|
|
||||||
def get_matches(self, location, query, candidates=None,
|
def get_matches(self, location, query, candidates=None,
|
||||||
allow_recursion=True):
|
allow_recursion=True):
|
||||||
@ -455,6 +501,7 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
if query and query.strip():
|
if query and query.strip():
|
||||||
# get metadata key associated with the search term. Eliminates
|
# get metadata key associated with the search term. Eliminates
|
||||||
# dealing with plurals and other aliases
|
# dealing with plurals and other aliases
|
||||||
|
original_location = location
|
||||||
location = self.field_metadata.search_term_to_field_key(icu_lower(location.strip()))
|
location = self.field_metadata.search_term_to_field_key(icu_lower(location.strip()))
|
||||||
# grouped search terms
|
# grouped search terms
|
||||||
if isinstance(location, list):
|
if isinstance(location, list):
|
||||||
@ -505,21 +552,19 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
return self.get_numeric_matches(location, query[1:],
|
return self.get_numeric_matches(location, query[1:],
|
||||||
candidates, val_func=vf)
|
candidates, val_func=vf)
|
||||||
|
|
||||||
|
# special case: identifiers. isbn is a special case within the case
|
||||||
|
if location == 'identifiers':
|
||||||
|
if original_location == 'isbn':
|
||||||
|
return self.get_keypair_matches('identifiers',
|
||||||
|
'=isbn:'+query, candidates)
|
||||||
|
return self.get_keypair_matches(location, query, candidates)
|
||||||
|
|
||||||
# check for user categories
|
# check for user categories
|
||||||
if len(location) >= 2 and location.startswith('@'):
|
if len(location) >= 2 and location.startswith('@'):
|
||||||
return self.get_user_category_matches(location[1:], query.lower(),
|
return self.get_user_category_matches(location[1:], query.lower(),
|
||||||
candidates)
|
candidates)
|
||||||
# everything else, or 'all' matches
|
# everything else, or 'all' matches
|
||||||
matchkind = CONTAINS_MATCH
|
matchkind, query = self._matchkind(query)
|
||||||
if (len(query) > 1):
|
|
||||||
if query.startswith('\\'):
|
|
||||||
query = query[1:]
|
|
||||||
elif query.startswith('='):
|
|
||||||
matchkind = EQUALS_MATCH
|
|
||||||
query = query[1:]
|
|
||||||
elif query.startswith('~'):
|
|
||||||
matchkind = REGEXP_MATCH
|
|
||||||
query = query[1:]
|
|
||||||
if matchkind != REGEXP_MATCH:
|
if matchkind != REGEXP_MATCH:
|
||||||
# leave case in regexps because it can be significant e.g. \S \W \D
|
# leave case in regexps because it can be significant e.g. \S \W \D
|
||||||
query = icu_lower(query)
|
query = icu_lower(query)
|
||||||
|
@ -119,15 +119,6 @@ class FieldMetadata(dict):
|
|||||||
'search_terms':['formats', 'format'],
|
'search_terms':['formats', 'format'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':True}),
|
'is_category':True}),
|
||||||
('identifiers', {'table':None,
|
|
||||||
'column':None,
|
|
||||||
'datatype':'text',
|
|
||||||
'is_multiple':',',
|
|
||||||
'kind':'field',
|
|
||||||
'name':_('Identifiers'),
|
|
||||||
'search_terms':['identifiers', 'identifier'],
|
|
||||||
'is_custom':False,
|
|
||||||
'is_category':True}),
|
|
||||||
('publisher', {'table':'publishers',
|
('publisher', {'table':'publishers',
|
||||||
'column':'name',
|
'column':'name',
|
||||||
'link_column':'publisher',
|
'link_column':'publisher',
|
||||||
@ -171,6 +162,15 @@ class FieldMetadata(dict):
|
|||||||
'search_terms':['tags', 'tag'],
|
'search_terms':['tags', 'tag'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':True}),
|
'is_category':True}),
|
||||||
|
('identifiers', {'table':None,
|
||||||
|
'column':None,
|
||||||
|
'datatype':'text',
|
||||||
|
'is_multiple':',',
|
||||||
|
'kind':'field',
|
||||||
|
'name':_('Identifiers'),
|
||||||
|
'search_terms':['identifiers', 'identifier', 'isbn'],
|
||||||
|
'is_custom':False,
|
||||||
|
'is_category':True}),
|
||||||
('author_sort',{'table':None,
|
('author_sort',{'table':None,
|
||||||
'column':None,
|
'column':None,
|
||||||
'datatype':'text',
|
'datatype':'text',
|
||||||
@ -206,15 +206,6 @@ class FieldMetadata(dict):
|
|||||||
'search_terms':['cover'],
|
'search_terms':['cover'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False}),
|
'is_category':False}),
|
||||||
('flags', {'table':None,
|
|
||||||
'column':None,
|
|
||||||
'datatype':'text',
|
|
||||||
'is_multiple':None,
|
|
||||||
'kind':'field',
|
|
||||||
'name':None,
|
|
||||||
'search_terms':[],
|
|
||||||
'is_custom':False,
|
|
||||||
'is_category':False}),
|
|
||||||
('id', {'table':None,
|
('id', {'table':None,
|
||||||
'column':None,
|
'column':None,
|
||||||
'datatype':'int',
|
'datatype':'int',
|
||||||
@ -224,22 +215,13 @@ class FieldMetadata(dict):
|
|||||||
'search_terms':[],
|
'search_terms':[],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False}),
|
'is_category':False}),
|
||||||
('isbn', {'table':None,
|
('last_modified', {'table':None,
|
||||||
'column':None,
|
'column':None,
|
||||||
'datatype':'text',
|
'datatype':'datetime',
|
||||||
'is_multiple':None,
|
'is_multiple':None,
|
||||||
'kind':'field',
|
'kind':'field',
|
||||||
'name':None,
|
'name':_('Date'),
|
||||||
'search_terms':['isbn'],
|
'search_terms':['last_modified'],
|
||||||
'is_custom':False,
|
|
||||||
'is_category':False}),
|
|
||||||
('lccn', {'table':None,
|
|
||||||
'column':None,
|
|
||||||
'datatype':'text',
|
|
||||||
'is_multiple':None,
|
|
||||||
'kind':'field',
|
|
||||||
'name':None,
|
|
||||||
'search_terms':[],
|
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False}),
|
'is_category':False}),
|
||||||
('ondevice', {'table':None,
|
('ondevice', {'table':None,
|
||||||
@ -305,15 +287,6 @@ class FieldMetadata(dict):
|
|||||||
'search_terms':['date'],
|
'search_terms':['date'],
|
||||||
'is_custom':False,
|
'is_custom':False,
|
||||||
'is_category':False}),
|
'is_category':False}),
|
||||||
('last_modified', {'table':None,
|
|
||||||
'column':None,
|
|
||||||
'datatype':'datetime',
|
|
||||||
'is_multiple':None,
|
|
||||||
'kind':'field',
|
|
||||||
'name':_('Date'),
|
|
||||||
'search_terms':['last_modified'],
|
|
||||||
'is_custom':False,
|
|
||||||
'is_category':False}),
|
|
||||||
('title', {'table':None,
|
('title', {'table':None,
|
||||||
'column':None,
|
'column':None,
|
||||||
'datatype':'text',
|
'datatype':'text',
|
||||||
|
@ -673,6 +673,8 @@ class BrowseServer(object):
|
|||||||
categories = [categories]
|
categories = [categories]
|
||||||
dbtags = []
|
dbtags = []
|
||||||
for category in categories:
|
for category in categories:
|
||||||
|
if category not in ccache:
|
||||||
|
continue
|
||||||
dbtag = None
|
dbtag = None
|
||||||
for tag in ccache[key]:
|
for tag in ccache[key]:
|
||||||
if tag.name == category:
|
if tag.name == category:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user