server/tags: improve tag export performance

2000 ms --> 250 ms (including overhead of unknown size).
Not bad if you ask me.
This commit is contained in:
rr- 2016-07-26 23:04:53 +02:00
parent 3f2717843a
commit 8ef0017531
2 changed files with 49 additions and 29 deletions

View file

@ -55,34 +55,51 @@ def serialize_tag(tag, options=None):
options) options)
def export_to_json(): def export_to_json():
tags = {}
categories = {}
for result in db.session.query(
db.TagCategory.tag_category_id,
db.TagCategory.name,
db.TagCategory.color).all():
categories[result[0]] = {
'name': result[1],
'color': result[2],
}
for result in db.session.query(db.TagName.tag_id, db.TagName.name).all():
if not result[0] in tags:
tags[result[0]] = {'names': []}
tags[result[0]]['names'].append(result[1])
for result in db.session \
.query(db.TagSuggestion.parent_id, db.TagName.name) \
.join(db.TagName, db.TagName.tag_id == db.TagSuggestion.child_id) \
.all():
if not 'suggestions' in tags[result[0]]:
tags[result[0]]['suggestions'] = []
tags[result[0]]['suggestions'].append(result[1])
for result in db.session \
.query(db.TagImplication.parent_id, db.TagName.name) \
.join(db.TagName, db.TagName.tag_id == db.TagImplication.child_id) \
.all():
if not 'implications' in tags[result[0]]:
tags[result[0]]['implications'] = []
tags[result[0]]['implications'].append(result[1])
for result in db.session.query(
db.Tag.tag_id,
db.Tag.category_id,
db.Tag.post_count).all():
tags[result[0]]['category'] = categories[result[1]]['name']
tags[result[0]]['usages'] = result[2]
output = { output = {
'tags': [], 'categories': list(categories.values()),
'categories': [], 'tags': list(tags.values()),
} }
all_tags = db.session \
.query(db.Tag) \
.options(
sqlalchemy.orm.joinedload('suggestions'),
sqlalchemy.orm.joinedload('implications')) \
.all()
for tag in all_tags:
item = {
'names': [tag_name.name for tag_name in tag.names],
'usages': tag.post_count,
'category': tag.category.name,
}
if len(tag.suggestions):
item['suggestions'] = \
[rel.names[0].name for rel in tag.suggestions]
if len(tag.implications):
item['implications'] = \
[rel.names[0].name for rel in tag.implications]
output['tags'].append(item)
for category in tag_categories.get_all_categories():
output['categories'].append({
'name': category.name,
'color': category.color,
})
export_path = os.path.join(config.config['data_dir'], 'tags.json') export_path = os.path.join(config.config['data_dir'], 'tags.json')
with open(export_path, 'w') as handle: with open(export_path, 'w') as handle:
handle.write(json.dumps(output, separators=(',', ':'))) handle.write(json.dumps(output, separators=(',', ':')))

View file

@ -8,6 +8,7 @@ def test_export(
tmpdir, tmpdir,
query_counter, query_counter,
config_injector, config_injector,
post_factory,
tag_factory, tag_factory,
tag_category_factory): tag_category_factory):
config_injector({ config_injector({
@ -22,10 +23,12 @@ def test_export(
imp1 = tag_factory(names=['imp1'], category=cat1) imp1 = tag_factory(names=['imp1'], category=cat1)
imp2 = tag_factory(names=['imp2'], category=cat1) imp2 = tag_factory(names=['imp2'], category=cat1)
tag = tag_factory(names=['alias1', 'alias2'], category=cat2) tag = tag_factory(names=['alias1', 'alias2'], category=cat2)
tag.post_count = 1
db.session.add_all([tag, sug1, sug2, imp1, imp2, cat1, cat2]) db.session.add_all([tag, sug1, sug2, imp1, imp2, cat1, cat2])
post = post_factory()
post.tags = [tag]
db.session.flush() db.session.flush()
db.session.add_all([ db.session.add_all([
post,
db.TagSuggestion(tag.tag_id, sug1.tag_id), db.TagSuggestion(tag.tag_id, sug1.tag_id),
db.TagSuggestion(tag.tag_id, sug2.tag_id), db.TagSuggestion(tag.tag_id, sug2.tag_id),
db.TagImplication(tag.tag_id, imp1.tag_id), db.TagImplication(tag.tag_id, imp1.tag_id),
@ -35,7 +38,7 @@ def test_export(
with query_counter: with query_counter:
tags.export_to_json() tags.export_to_json()
assert len(query_counter.statements) == 2 assert len(query_counter.statements) == 5
export_path = os.path.join(config.config['data_dir'], 'tags.json') export_path = os.path.join(config.config['data_dir'], 'tags.json')
assert os.path.exists(export_path) assert os.path.exists(export_path)