server/tags: reduce number of queries
On a test page with 50 tags, 158 queries were reduced to 3: 1. Get the authenticated user 2. Get tags for given page 3. Count all tags Looks just about right.
This commit is contained in:
parent
d813601d92
commit
339c9a3333
8 changed files with 33 additions and 17 deletions
|
@ -11,9 +11,12 @@ class BaseSearchConfig(object):
|
||||||
SORT_DESC = -1
|
SORT_DESC = -1
|
||||||
SORT_ASC = 1
|
SORT_ASC = 1
|
||||||
|
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def create_count_query(self):
|
||||||
|
return self.create_filter_query()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def anonymous_filter(self):
|
def anonymous_filter(self):
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -3,7 +3,7 @@ from szurubooru import db
|
||||||
from szurubooru.search.base_search_config import BaseSearchConfig
|
from szurubooru.search.base_search_config import BaseSearchConfig
|
||||||
|
|
||||||
class CommentSearchConfig(BaseSearchConfig):
|
class CommentSearchConfig(BaseSearchConfig):
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
return db.session.query(db.Comment).join(db.User)
|
return db.session.query(db.Comment).join(db.User)
|
||||||
|
|
||||||
def finalize_query(self, query):
|
def finalize_query(self, query):
|
||||||
|
|
|
@ -22,7 +22,7 @@ def _type_transformer(value):
|
||||||
value, available_types))
|
value, available_types))
|
||||||
|
|
||||||
class PostSearchConfig(BaseSearchConfig):
|
class PostSearchConfig(BaseSearchConfig):
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
return db.session.query(db.Post)
|
return db.session.query(db.Post)
|
||||||
|
|
||||||
def finalize_query(self, query):
|
def finalize_query(self, query):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import re
|
import re
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from szurubooru import errors
|
from szurubooru import db, errors
|
||||||
from szurubooru.search import criteria
|
from szurubooru.search import criteria
|
||||||
|
|
||||||
class SearchExecutor(object):
|
class SearchExecutor(object):
|
||||||
|
@ -17,15 +17,22 @@ class SearchExecutor(object):
|
||||||
Parse input and return tuple containing total record count and filtered
|
Parse input and return tuple containing total record count and filtered
|
||||||
entities.
|
entities.
|
||||||
'''
|
'''
|
||||||
filter_query = self._prepare(query_text)
|
filter_query = self.config.create_filter_query()
|
||||||
|
filter_query = filter_query.options(sqlalchemy.orm.lazyload('*'))
|
||||||
|
filter_query = self._prepare(filter_query, query_text)
|
||||||
entities = filter_query \
|
entities = filter_query \
|
||||||
.offset((page - 1) * page_size).limit(page_size).all()
|
.offset((page - 1) * page_size) \
|
||||||
count_query = filter_query.statement \
|
.limit(page_size) \
|
||||||
|
.all()
|
||||||
|
|
||||||
|
count_query = self.config.create_count_query()
|
||||||
|
count_query = count_query.options(sqlalchemy.orm.lazyload('*'))
|
||||||
|
count_query = self._prepare(count_query, query_text)
|
||||||
|
count_statement = count_query \
|
||||||
|
.statement \
|
||||||
.with_only_columns([sqlalchemy.func.count()]) \
|
.with_only_columns([sqlalchemy.func.count()]) \
|
||||||
.order_by(None)
|
.order_by(None)
|
||||||
count = filter_query.session \
|
count = db.session.execute(count_statement).scalar()
|
||||||
.execute(count_query) \
|
|
||||||
.scalar()
|
|
||||||
return (count, entities)
|
return (count, entities)
|
||||||
|
|
||||||
def execute_and_serialize(self, ctx, serializer):
|
def execute_and_serialize(self, ctx, serializer):
|
||||||
|
@ -41,10 +48,8 @@ class SearchExecutor(object):
|
||||||
'results': [serializer(entity) for entity in entities],
|
'results': [serializer(entity) for entity in entities],
|
||||||
}
|
}
|
||||||
|
|
||||||
def _prepare(self, query_text):
|
def _prepare(self, query, query_text):
|
||||||
''' Parse input and return SQLAlchemy query. '''
|
''' Parse input and return SQLAlchemy query. '''
|
||||||
query = self.config.create_query() \
|
|
||||||
.options(sqlalchemy.orm.lazyload('*'))
|
|
||||||
for token in re.split(r'\s+', (query_text or '').lower()):
|
for token in re.split(r'\s+', (query_text or '').lower()):
|
||||||
if not token:
|
if not token:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -2,7 +2,7 @@ from szurubooru import db
|
||||||
from szurubooru.search.base_search_config import BaseSearchConfig
|
from szurubooru.search.base_search_config import BaseSearchConfig
|
||||||
|
|
||||||
class SnapshotSearchConfig(BaseSearchConfig):
|
class SnapshotSearchConfig(BaseSearchConfig):
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
return db.session.query(db.Snapshot)
|
return db.session.query(db.Snapshot)
|
||||||
|
|
||||||
def finalize_query(self, query):
|
def finalize_query(self, query):
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
|
from sqlalchemy.orm import joinedload
|
||||||
from sqlalchemy.sql.expression import func
|
from sqlalchemy.sql.expression import func
|
||||||
from szurubooru import db
|
from szurubooru import db
|
||||||
from szurubooru.search.base_search_config import BaseSearchConfig
|
from szurubooru.search.base_search_config import BaseSearchConfig
|
||||||
|
|
||||||
class TagSearchConfig(BaseSearchConfig):
|
class TagSearchConfig(BaseSearchConfig):
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
|
return self.create_count_query().options(
|
||||||
|
joinedload(db.Tag.names),
|
||||||
|
joinedload(db.Tag.category),
|
||||||
|
joinedload(db.Tag.suggestions).joinedload(db.Tag.names),
|
||||||
|
joinedload(db.Tag.implications).joinedload(db.Tag.names)
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_count_query(self):
|
||||||
return db.session.query(db.Tag)
|
return db.session.query(db.Tag)
|
||||||
|
|
||||||
def finalize_query(self, query):
|
def finalize_query(self, query):
|
||||||
|
|
|
@ -5,7 +5,7 @@ from szurubooru.search.base_search_config import BaseSearchConfig
|
||||||
class UserSearchConfig(BaseSearchConfig):
|
class UserSearchConfig(BaseSearchConfig):
|
||||||
''' Executes searches related to the users. '''
|
''' Executes searches related to the users. '''
|
||||||
|
|
||||||
def create_query(self):
|
def create_filter_query(self):
|
||||||
return db.session.query(db.User)
|
return db.session.query(db.User)
|
||||||
|
|
||||||
def finalize_query(self, query):
|
def finalize_query(self, query):
|
||||||
|
|
|
@ -56,7 +56,6 @@ 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])
|
||||||
print(actual_post_ids, expected_post_ids)
|
|
||||||
assert actual_count == len(expected_post_ids)
|
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)
|
||||||
|
|
Loading…
Reference in a new issue