faster filters
This commit is contained in:
parent
27908619ef
commit
2b3edd40dc
5 changed files with 68 additions and 19 deletions
|
@ -44,43 +44,42 @@ def find(data):
|
||||||
if 'group' in q:
|
if 'group' in q:
|
||||||
names = {}
|
names = {}
|
||||||
groups = {}
|
groups = {}
|
||||||
|
sortvalues = {}
|
||||||
_keydata = data.copy()
|
_keydata = data.copy()
|
||||||
for key in ('range', 'position'):
|
for key in ('range', 'position', 'positions'):
|
||||||
if key in _keydata:
|
if key in _keydata:
|
||||||
del _keydata[key]
|
del _keydata[key]
|
||||||
key = 'group:' + hashlib.sha1(json.dumps(_keydata).encode('utf-8')).hexdigest()
|
key = 'group:' + hashlib.sha1(json.dumps(_keydata, sort_keys=True).encode('utf-8')).hexdigest()
|
||||||
g = state.cache.get(key)
|
g = state.cache.get(key)
|
||||||
if g is None:
|
if g is None:
|
||||||
items = q['qs'].options(load_only('id'))
|
items = q['qs'].options(load_only('id'))
|
||||||
qs = models.Find.query.filter_by(key=q['group'])
|
qs = models.Find.query.filter_by(key=q['group'])
|
||||||
if items.first():
|
if items.first():
|
||||||
qs = qs.filter(models.Find.item_id.in_(items))
|
qs = qs.filter(models.Find.item_id.in_(items))
|
||||||
for f in qs.values('value', 'findvalue'):
|
for f in qs.values('value', 'findvalue', 'sortvalue'):
|
||||||
value = f[0]
|
value = f[0]
|
||||||
findvalue = f[1]
|
findvalue = f[1]
|
||||||
|
sortvalue = f[2]
|
||||||
if findvalue not in groups:
|
if findvalue not in groups:
|
||||||
groups[findvalue] = 0
|
groups[findvalue] = 0
|
||||||
groups[findvalue] += 1
|
groups[findvalue] += 1
|
||||||
names[findvalue] = value
|
names[findvalue] = value
|
||||||
|
sortvalues[value] = sortvalue
|
||||||
g = [{'name': names[k], 'items': groups[k]} for k in groups]
|
g = [{'name': names[k], 'items': groups[k]} for k in groups]
|
||||||
else:
|
else:
|
||||||
g = []
|
g = []
|
||||||
if 'sort' in q:
|
if 'sort' in q:
|
||||||
sort_type = utils.get_by_id(settings.config['itemKeys'], q['group']).get('sortType')
|
reverse = q['sort'][0]['operator'] == '-'
|
||||||
def _sort_key(k):
|
def _sort_key(k):
|
||||||
if sort_type == 'person':
|
name = sortvalues[k['name']]
|
||||||
name = get_sort_name(k['name'])
|
if not name:
|
||||||
else:
|
name = '\uffff' if not reverse else ''
|
||||||
name = k['name']
|
|
||||||
if isinstance(name, str):
|
|
||||||
name = unicodedata.normalize('NFKD', name).lower()
|
|
||||||
items = k['items']
|
items = k['items']
|
||||||
if q['sort'][0]['key'] == 'name':
|
if q['sort'][0]['key'] == 'name':
|
||||||
v = (name, items)
|
v = (name, items)
|
||||||
else:
|
else:
|
||||||
v = (-items, name)
|
v = (-items, name)
|
||||||
return v
|
return v
|
||||||
reverse = q['sort'][0]['operator'] == '-'
|
|
||||||
if q['sort'][0]['key'] == 'items':
|
if q['sort'][0]['key'] == 'items':
|
||||||
reverse = not reverse
|
reverse = not reverse
|
||||||
g.sort(key=_sort_key, reverse=reverse)
|
g.sort(key=_sort_key, reverse=reverse)
|
||||||
|
|
|
@ -171,12 +171,8 @@ class Item(db.Model):
|
||||||
value = list(map(get_sort_name, value))
|
value = list(map(get_sort_name, value))
|
||||||
value = ox.sort_string('\n'.join(value)).lower()
|
value = ox.sort_string('\n'.join(value)).lower()
|
||||||
elif sort_type == 'title':
|
elif sort_type == 'title':
|
||||||
if isinstance(value, dict):
|
value = self.get_sorttitle().lower()
|
||||||
value = list(value.values())
|
value = utils.sort_title(value)
|
||||||
if isinstance(value, list):
|
|
||||||
value = ''.join(value)
|
|
||||||
value = ox.get_sort_title(value)
|
|
||||||
value = utils.sort_title(value).lower()
|
|
||||||
elif sort_type == 'boolean':
|
elif sort_type == 'boolean':
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -204,6 +200,16 @@ class Item(db.Model):
|
||||||
if f.value != v:
|
if f.value != v:
|
||||||
f.findvalue = unicodedata.normalize('NFKD', v).lower()
|
f.findvalue = unicodedata.normalize('NFKD', v).lower()
|
||||||
f.value = v
|
f.value = v
|
||||||
|
if k in self.filter_keys:
|
||||||
|
sort_type = utils.get_by_id(settings.config['itemKeys'], k).get('sortType')
|
||||||
|
if sort_type == 'person':
|
||||||
|
f.sortvalue = get_sort_name(f.value)
|
||||||
|
else:
|
||||||
|
f.sortvalue = f.value
|
||||||
|
if f.sortvalue:
|
||||||
|
f.sortvalue = unicodedata.normalize('NFKD', f.sortvalue).lower()
|
||||||
|
else:
|
||||||
|
f.sortvalue = None
|
||||||
state.db.session.add(f)
|
state.db.session.add(f)
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
|
@ -285,7 +291,8 @@ class Item(db.Model):
|
||||||
'series',
|
'series',
|
||||||
'sharemetadata',
|
'sharemetadata',
|
||||||
'tableofcontents',
|
'tableofcontents',
|
||||||
'title'
|
'title',
|
||||||
|
'sorttitle'
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_metadata(self, data, modified=None):
|
def update_metadata(self, data, modified=None):
|
||||||
|
@ -320,6 +327,13 @@ class Item(db.Model):
|
||||||
def get_hash(self):
|
def get_hash(self):
|
||||||
return utils.get_meta_hash(self.meta.copy())
|
return utils.get_meta_hash(self.meta.copy())
|
||||||
|
|
||||||
|
def get_sorttitle(self):
|
||||||
|
title = self.meta.get('sorttitle')
|
||||||
|
if title is None:
|
||||||
|
title = self.meta.get('title', 'Untitled')
|
||||||
|
title = ox.get_sort_title(title)
|
||||||
|
return title
|
||||||
|
|
||||||
def sync_metadata(self):
|
def sync_metadata(self):
|
||||||
from user.models import Metadata
|
from user.models import Metadata
|
||||||
if self.meta.get('sharemetadata'):
|
if self.meta.get('sharemetadata'):
|
||||||
|
@ -583,6 +597,7 @@ class Find(db.Model):
|
||||||
key = sa.Column(sa.String(200), index=True)
|
key = sa.Column(sa.String(200), index=True)
|
||||||
value = sa.Column(sa.Text())
|
value = sa.Column(sa.Text())
|
||||||
findvalue = sa.Column(sa.Text(), index=True)
|
findvalue = sa.Column(sa.Text(), index=True)
|
||||||
|
sortvalue = sa.Column(sa.Text())
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s=%s' % (self.key, self.findvalue)
|
return '%s=%s' % (self.key, self.findvalue)
|
||||||
|
@ -782,6 +797,11 @@ def update_sort_table():
|
||||||
sql = []
|
sql = []
|
||||||
for col in set(Item.sort_keys)-set(sort_indexes):
|
for col in set(Item.sort_keys)-set(sort_indexes):
|
||||||
sql.append('CREATE INDEX ix_sort_{col} ON sort ({col})'.format(col=col))
|
sql.append('CREATE INDEX ix_sort_{col} ON sort ({col})'.format(col=col))
|
||||||
|
if not 'sortvalue' in db.get_table_columns('find'):
|
||||||
|
create_table = str(CreateTable(Find.__table__).compile(db.engine)).split('\n')
|
||||||
|
col = 'sortvalue'
|
||||||
|
add = [r for r in create_table if '\t%s ' % col in r][0].strip()[:-1]
|
||||||
|
sql.append('ALTER TABLE find ADD '+add)
|
||||||
if sql:
|
if sql:
|
||||||
with db.session() as s:
|
with db.session() as s:
|
||||||
for q in sql:
|
for q in sql:
|
||||||
|
|
|
@ -99,4 +99,4 @@ USER_AGENT = 'OpenMediaLibrary/%s' % VERSION
|
||||||
|
|
||||||
DEBUG_HTTP = server.get('debug_http', False)
|
DEBUG_HTTP = server.get('debug_http', False)
|
||||||
|
|
||||||
DB_VERSION = 9
|
DB_VERSION = 10
|
||||||
|
|
|
@ -77,6 +77,7 @@ CREATE TABLE find (
|
||||||
"key" VARCHAR(200),
|
"key" VARCHAR(200),
|
||||||
value TEXT,
|
value TEXT,
|
||||||
findvalue TEXT,
|
findvalue TEXT,
|
||||||
|
sortvalue TEXT,
|
||||||
PRIMARY KEY (id),
|
PRIMARY KEY (id),
|
||||||
FOREIGN KEY(item_id) REFERENCES item (id)
|
FOREIGN KEY(item_id) REFERENCES item (id)
|
||||||
);
|
);
|
||||||
|
|
|
@ -307,6 +307,8 @@ class Update(Thread):
|
||||||
db_version = migrate_7()
|
db_version = migrate_7()
|
||||||
if db_version < 9:
|
if db_version < 9:
|
||||||
db_version = migrate_8()
|
db_version = migrate_8()
|
||||||
|
if db_version < 10:
|
||||||
|
db_version = migrate_10()
|
||||||
settings.server['db_version'] = settings.DB_VERSION
|
settings.server['db_version'] = settings.DB_VERSION
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -450,3 +452,30 @@ def migrate_8():
|
||||||
session.delete(peer)
|
session.delete(peer)
|
||||||
session.commit()
|
session.commit()
|
||||||
return 8
|
return 8
|
||||||
|
|
||||||
|
def migrate_10():
|
||||||
|
with db.session() as session:
|
||||||
|
from item.models import Item, Find
|
||||||
|
from utils import get_by_id
|
||||||
|
from item.person import get_sort_name
|
||||||
|
import unicodedata
|
||||||
|
sort_names = {}
|
||||||
|
for f in Find.query.filter(Find.key.in_(Item.sort_keys)):
|
||||||
|
if f.key in Item.filter_keys:
|
||||||
|
sort_type = get_by_id(settings.config['itemKeys'], f.key).get('sortType')
|
||||||
|
if sort_type == 'person':
|
||||||
|
if f.value in sort_names:
|
||||||
|
f.sortvalue = sort_names[f.value]
|
||||||
|
else:
|
||||||
|
f.sortvalue = sort_names[f.value] = get_sort_name(f.value)
|
||||||
|
else:
|
||||||
|
f.sortvalue = f.value
|
||||||
|
if f.sortvalue:
|
||||||
|
f.sortvalue = unicodedata.normalize('NFKD', f.sortvalue).lower()
|
||||||
|
else:
|
||||||
|
f.sortvalue = None
|
||||||
|
else:
|
||||||
|
f.sortvalue = None
|
||||||
|
session.add(f)
|
||||||
|
session.commit()
|
||||||
|
return 10
|
||||||
|
|
Loading…
Reference in a new issue