Using sqlalchemy's subqueryload to fetch tags works like this: 1. Get basic info about posts with query X 2. Copy query X 3. SELECT all tags WHERE post_id IN (SELECT post_ids FROM query X) 4. Associate the resulting tags with the posts When original query contains .order_by(func.random()), it looks like this: 1. SELECT post.* FROM post ORDER BY random() LIMIT 10 2. Copy "ORDER BY random() LIMIT 10" 3. SELECT tag.* FROM tag WHERE tag.post_id IN ( SELECT id FROM post ORDER BY random() LIMIT 10) 4. Disaster! Each post now has completely arbitrary tags! To circumvent this, we replace eager loading with lazy loading. This generates one extra query for each result row, but it has no chance of producing such anomalies. This behavior is activated only for queries containing "sort:random" and derivatives so it shouldn't hit performance too much.
28 lines
1.1 KiB
Python
28 lines
1.1 KiB
Python
from szurubooru import db
|
|
from szurubooru.search.configs import util as search_util
|
|
from szurubooru.search.configs.base_search_config import BaseSearchConfig
|
|
|
|
|
|
class SnapshotSearchConfig(BaseSearchConfig):
|
|
def create_filter_query(self, _disable_eager_loads):
|
|
return db.session.query(db.Snapshot)
|
|
|
|
def create_count_query(self, _disable_eager_loads):
|
|
return db.session.query(db.Snapshot)
|
|
|
|
def create_around_query(self):
|
|
raise NotImplementedError()
|
|
|
|
def finalize_query(self, query):
|
|
return query.order_by(db.Snapshot.creation_time.desc())
|
|
|
|
@property
|
|
def named_filters(self):
|
|
return {
|
|
'type': search_util.create_str_filter(db.Snapshot.resource_type),
|
|
'id': search_util.create_str_filter(db.Snapshot.resource_name),
|
|
'date': search_util.create_date_filter(db.Snapshot.creation_time),
|
|
'time': search_util.create_date_filter(db.Snapshot.creation_time),
|
|
'operation': search_util.create_str_filter(db.Snapshot.operation),
|
|
'user': search_util.create_str_filter(db.User.name),
|
|
}
|