server/search: improve performance

This commit is contained in:
rr- 2016-05-30 20:01:14 +02:00
parent 5427b0d25a
commit 48bcbbff83
6 changed files with 26 additions and 13 deletions

View file

@ -116,7 +116,7 @@ class Post(Base):
'Post', 'Post',
secondary='post_relation', secondary='post_relation',
primaryjoin=post_id == PostRelation.parent_id, primaryjoin=post_id == PostRelation.parent_id,
secondaryjoin=post_id == PostRelation.child_id) secondaryjoin=post_id == PostRelation.child_id, lazy='joined')
features = relationship( features = relationship(
'PostFeature', cascade='all, delete-orphan', lazy='joined') 'PostFeature', cascade='all, delete-orphan', lazy='joined')
scores = relationship( scores = relationship(

View file

@ -79,7 +79,7 @@ def serialize_post(post, authenticated_user):
'contentUrl': get_post_content_url(post), 'contentUrl': get_post_content_url(post),
'thumbnailUrl': get_post_thumbnail_url(post), 'thumbnailUrl': get_post_thumbnail_url(post),
'flags': post.flags, 'flags': post.flags,
'tags': [tag.first_name for tag in post.tags], 'tags': [tag.names[0].name for tag in post.tags],
'relations': [rel.post_id for rel in post.relations], 'relations': [rel.post_id for rel in post.relations],
'notes': sorted( 'notes': sorted(
[ serialize_note(note) for note in post.notes], [ serialize_note(note) for note in post.notes],

View file

@ -21,11 +21,13 @@ def delete_score(entity, user):
db.session.delete(score_entity) db.session.delete(score_entity)
def get_score(entity, user): def get_score(entity, user):
score_entity = _get_score_entity(entity, user) table, get_column = _get_table_info(entity)
if score_entity: row = db.session \
return score_entity.score .query(table.score) \
else: .filter(get_column(table) == get_column(entity)) \
return 0 .filter(table.user_id == user.user_id) \
.one_or_none()
return row[0] if row else 0
def set_score(entity, user, score): def set_score(entity, user, score):
if not score: if not score:

View file

@ -1,3 +1,4 @@
from sqlalchemy.orm import subqueryload
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from szurubooru import db, errors from szurubooru import db, errors
from szurubooru.func import util from szurubooru.func import util
@ -23,6 +24,16 @@ def _type_transformer(value):
class PostSearchConfig(BaseSearchConfig): class PostSearchConfig(BaseSearchConfig):
def create_filter_query(self): def create_filter_query(self):
return self.create_count_query() \
.options(
subqueryload(db.Post.user),
subqueryload(db.Post.relations),
subqueryload(db.Post.notes),
subqueryload(db.Post.tags).subqueryload(db.Tag.names),
subqueryload(db.Post.favorited_by),
)
def create_count_query(self):
return db.session.query(db.Post) return db.session.query(db.Post)
def finalize_query(self, query): def finalize_query(self, query):

View file

@ -1,4 +1,4 @@
from sqlalchemy.orm import joinedload from sqlalchemy.orm import subqueryload
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from szurubooru import db from szurubooru import db
from szurubooru.func import util from szurubooru.func import util
@ -9,10 +9,10 @@ class TagSearchConfig(BaseSearchConfig):
return self.create_count_query() \ return self.create_count_query() \
.join(db.TagCategory) \ .join(db.TagCategory) \
.options( .options(
joinedload(db.Tag.names), subqueryload(db.Tag.names),
joinedload(db.Tag.category), subqueryload(db.Tag.category),
joinedload(db.Tag.suggestions).joinedload(db.Tag.names), subqueryload(db.Tag.suggestions).joinedload(db.Tag.names),
joinedload(db.Tag.implications).joinedload(db.Tag.names) subqueryload(db.Tag.implications).joinedload(db.Tag.names)
) )
def create_count_query(self): def create_count_query(self):

View file

@ -56,11 +56,11 @@ def verify_unpaged(executor):
actual_count, actual_posts = executor.execute( actual_count, actual_posts = executor.execute(
input, page=1, page_size=100) input, page=1, page_size=100)
actual_post_ids = list([p.post_id for p in actual_posts]) actual_post_ids = list([p.post_id for p in actual_posts])
assert actual_count == len(expected_post_ids)
if not test_order: if not test_order:
actual_post_ids = sorted(actual_post_ids) actual_post_ids = sorted(actual_post_ids)
expected_post_ids = sorted(expected_post_ids) expected_post_ids = sorted(expected_post_ids)
assert actual_post_ids == expected_post_ids assert actual_post_ids == expected_post_ids
assert actual_count == len(expected_post_ids)
return verify return verify
@pytest.mark.parametrize('input,expected_post_ids', [ @pytest.mark.parametrize('input,expected_post_ids', [