Implement /ajax/search

This commit is contained in:
Kovid Goyal 2015-06-15 20:39:02 +05:30
parent de39f5f887
commit 459899a11a
3 changed files with 39 additions and 2 deletions

View File

@ -519,3 +519,36 @@ def books_in(ctx, rd, encoded_category, encoded_item, library_id):
result['additional_fields'] = additional_fields
return result
# }}}
@endpoint('/ajax/search/{library_id=None}', postprocess=json)
def search(ctx, rd, library_id):
'''
Return the books (as list of ids) matching the specified search query.
Optional: ?num=100&offset=0&sort=title&sort_order=asc&get_additional_fields=
'''
db = get_db(ctx, library_id)
with db.safe_read_lock:
query = rd.query.get('query')
num, offset = get_pagination(rd.query)
sort, sort_order = rd.query.get('sort', 'title'), rd.query.get('sort_order')
sort_order = ensure_val(sort_order, 'asc', 'desc')
sfield = sanitize_sort_field_name(db.field_metadata, sort)
if sfield not in db.field_metadata.sortable_field_keys():
raise HTTPNotFound('%s is not a valid sort field'%sort)
if not query:
ids = ctx.allowed_book_ids(rd, db)
else:
ids = ctx.search(rd, db, query)
ids = db.multisort(fields=[(sfield, sort_order == 'asc')], ids_to_sort=ids)
total_num = len(ids)
ids = ids[offset:offset+num]
return {
'total_num': total_num, 'sort_order':sort_order,
'offset':offset, 'num':len(ids), 'sort':sort,
'base_url':ctx.url_for(search, library_id=db.server_library_id),
'query': query,
'book_ids':ids
}

View File

@ -108,7 +108,7 @@ class Context(object):
if old is None or old[0] < db.clear_search_cache_count:
matches = db.search(query, book_ids=restrict_to_ids)
cache[key] = old = (db.clear_search_cache_count, matches)
if len(self._search_cache) > self.SEARCH_CACHE_SIZE:
if len(cache) > self.SEARCH_CACHE_SIZE:
cache.popitem(last=False)
else:
cache[key] = old

View File

@ -8,6 +8,7 @@ __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
import httplib, zlib, json
from functools import partial
from urllib import urlencode
from calibre.srv.tests.base import LibraryBaseTest
@ -47,7 +48,7 @@ class ContentTest(LibraryBaseTest):
# }}}
def test_ajax_categories(self): # {{{
'Test /ajax/categories'
'Test /ajax/categories and /ajax/search'
with self.create_server() as server:
db = server.handler.router.ctx.get_library()
conn = server.connect()
@ -68,4 +69,7 @@ class ContentTest(LibraryBaseTest):
r, data = request(names['Tag One'], prefix='')
self.ae(r.status, httplib.OK)
self.ae(set(data['book_ids']), {1, 2})
r, data = request('/search?' + urlencode({'query': 'tags:"=Tag One"'}))
self.ae(r.status, httplib.OK)
self.ae(set(data['book_ids']), {1, 2})
# }}}