mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Add slim endpoints for entities to speed up filters (#460)
* Move performers image column to end of table * Remove redundant index
This commit is contained in:
@@ -19,24 +19,24 @@ query AllTags {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query AllPerformersForFilter {
|
query AllPerformersForFilter {
|
||||||
allPerformers {
|
allPerformersSlim {
|
||||||
...SlimPerformerData
|
...SlimPerformerData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query AllStudiosForFilter {
|
query AllStudiosForFilter {
|
||||||
allStudios {
|
allStudiosSlim {
|
||||||
...SlimStudioData
|
...SlimStudioData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
query AllMoviesForFilter {
|
query AllMoviesForFilter {
|
||||||
allMovies {
|
allMoviesSlim {
|
||||||
...SlimMovieData
|
...SlimMovieData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query AllTagsForFilter {
|
query AllTagsForFilter {
|
||||||
allTags {
|
allTagsSlim {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,13 @@ type Query {
|
|||||||
allMovies: [Movie!]!
|
allMovies: [Movie!]!
|
||||||
allTags: [Tag!]!
|
allTags: [Tag!]!
|
||||||
|
|
||||||
|
# Get everything with minimal metadata
|
||||||
|
|
||||||
|
allPerformersSlim: [Performer!]!
|
||||||
|
allStudiosSlim: [Studio!]!
|
||||||
|
allMoviesSlim: [Movie!]!
|
||||||
|
allTagsSlim: [Tag!]!
|
||||||
|
|
||||||
# Version
|
# Version
|
||||||
version: Version!
|
version: Version!
|
||||||
|
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ func (r *queryResolver) AllMovies(ctx context.Context) ([]*models.Movie, error)
|
|||||||
qb := models.NewMovieQueryBuilder()
|
qb := models.NewMovieQueryBuilder()
|
||||||
return qb.All()
|
return qb.All()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) AllMoviesSlim(ctx context.Context) ([]*models.Movie, error) {
|
||||||
|
qb := models.NewMovieQueryBuilder()
|
||||||
|
return qb.AllSlim()
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,3 +25,8 @@ func (r *queryResolver) AllPerformers(ctx context.Context) ([]*models.Performer,
|
|||||||
qb := models.NewPerformerQueryBuilder()
|
qb := models.NewPerformerQueryBuilder()
|
||||||
return qb.All()
|
return qb.All()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) AllPerformersSlim(ctx context.Context) ([]*models.Performer, error) {
|
||||||
|
qb := models.NewPerformerQueryBuilder()
|
||||||
|
return qb.AllSlim()
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,3 +25,8 @@ func (r *queryResolver) AllStudios(ctx context.Context) ([]*models.Studio, error
|
|||||||
qb := models.NewStudioQueryBuilder()
|
qb := models.NewStudioQueryBuilder()
|
||||||
return qb.All()
|
return qb.All()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) AllStudiosSlim(ctx context.Context) ([]*models.Studio, error) {
|
||||||
|
qb := models.NewStudioQueryBuilder()
|
||||||
|
return qb.AllSlim()
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,3 +16,8 @@ func (r *queryResolver) AllTags(ctx context.Context) ([]*models.Tag, error) {
|
|||||||
qb := models.NewTagQueryBuilder()
|
qb := models.NewTagQueryBuilder()
|
||||||
return qb.All()
|
return qb.All()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *queryResolver) AllTagsSlim(ctx context.Context) ([]*models.Tag, error) {
|
||||||
|
qb := models.NewTagQueryBuilder()
|
||||||
|
return qb.AllSlim()
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
var DB *sqlx.DB
|
var DB *sqlx.DB
|
||||||
var dbPath string
|
var dbPath string
|
||||||
var appSchemaVersion uint = 6
|
var appSchemaVersion uint = 7
|
||||||
var databaseSchemaVersion uint
|
var databaseSchemaVersion uint
|
||||||
|
|
||||||
const sqlite3Driver = "sqlite3_regexp"
|
const sqlite3Driver = "sqlite3_regexp"
|
||||||
|
|||||||
101
pkg/database/migrations/7_performer_optimization.up.sql
Normal file
101
pkg/database/migrations/7_performer_optimization.up.sql
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
DROP INDEX `performers_checksum_unique`;
|
||||||
|
DROP INDEX `index_performers_on_name`;
|
||||||
|
DROP INDEX `index_performers_on_checksum`;
|
||||||
|
ALTER TABLE `performers` RENAME TO `temp_old_performers`;
|
||||||
|
CREATE TABLE `performers` (
|
||||||
|
`id` integer not null primary key autoincrement,
|
||||||
|
`checksum` varchar(255) not null,
|
||||||
|
`name` varchar(255),
|
||||||
|
`gender` varchar(20),
|
||||||
|
`url` varchar(255),
|
||||||
|
`twitter` varchar(255),
|
||||||
|
`instagram` varchar(255),
|
||||||
|
`birthdate` date,
|
||||||
|
`ethnicity` varchar(255),
|
||||||
|
`country` varchar(255),
|
||||||
|
`eye_color` varchar(255),
|
||||||
|
`height` varchar(255),
|
||||||
|
`measurements` varchar(255),
|
||||||
|
`fake_tits` varchar(255),
|
||||||
|
`career_length` varchar(255),
|
||||||
|
`tattoos` varchar(255),
|
||||||
|
`piercings` varchar(255),
|
||||||
|
`aliases` varchar(255),
|
||||||
|
`favorite` boolean not null default '0',
|
||||||
|
`created_at` datetime not null,
|
||||||
|
`updated_at` datetime not null,
|
||||||
|
`image` blob not null
|
||||||
|
);
|
||||||
|
CREATE UNIQUE INDEX `performers_checksum_unique` on `performers` (`checksum`);
|
||||||
|
CREATE INDEX `index_performers_on_name` on `performers` (`name`);
|
||||||
|
INSERT INTO `performers` (
|
||||||
|
`id`,
|
||||||
|
`checksum`,
|
||||||
|
`name`,
|
||||||
|
`gender`,
|
||||||
|
`url`,
|
||||||
|
`twitter`,
|
||||||
|
`instagram`,
|
||||||
|
`birthdate`,
|
||||||
|
`ethnicity`,
|
||||||
|
`country`,
|
||||||
|
`eye_color`,
|
||||||
|
`height`,
|
||||||
|
`measurements`,
|
||||||
|
`fake_tits`,
|
||||||
|
`career_length`,
|
||||||
|
`tattoos`,
|
||||||
|
`piercings`,
|
||||||
|
`aliases`,
|
||||||
|
`favorite`,
|
||||||
|
`created_at`,
|
||||||
|
`updated_at`,
|
||||||
|
`image`
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
`id`,
|
||||||
|
`checksum`,
|
||||||
|
`name`,
|
||||||
|
`gender`,
|
||||||
|
`url`,
|
||||||
|
`twitter`,
|
||||||
|
`instagram`,
|
||||||
|
`birthdate`,
|
||||||
|
`ethnicity`,
|
||||||
|
`country`,
|
||||||
|
`eye_color`,
|
||||||
|
`height`,
|
||||||
|
`measurements`,
|
||||||
|
`fake_tits`,
|
||||||
|
`career_length`,
|
||||||
|
`tattoos`,
|
||||||
|
`piercings`,
|
||||||
|
`aliases`,
|
||||||
|
`favorite`,
|
||||||
|
`created_at`,
|
||||||
|
`updated_at`,
|
||||||
|
`image`
|
||||||
|
FROM `temp_old_performers`;
|
||||||
|
|
||||||
|
DROP INDEX `index_performers_scenes_on_scene_id`;
|
||||||
|
DROP INDEX `index_performers_scenes_on_performer_id`;
|
||||||
|
ALTER TABLE performers_scenes RENAME TO temp_old_performers_scenes;
|
||||||
|
CREATE TABLE `performers_scenes` (
|
||||||
|
`performer_id` integer,
|
||||||
|
`scene_id` integer,
|
||||||
|
foreign key(`performer_id`) references `performers`(`id`),
|
||||||
|
foreign key(`scene_id`) references `scenes`(`id`)
|
||||||
|
);
|
||||||
|
CREATE INDEX `index_performers_scenes_on_scene_id` on `performers_scenes` (`scene_id`);
|
||||||
|
CREATE INDEX `index_performers_scenes_on_performer_id` on `performers_scenes` (`performer_id`);
|
||||||
|
INSERT INTO `performers_scenes` (
|
||||||
|
`performer_id`,
|
||||||
|
`scene_id`
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
`performer_id`,
|
||||||
|
`scene_id`
|
||||||
|
FROM `temp_old_performers_scenes`;
|
||||||
|
|
||||||
|
DROP TABLE `temp_old_performers`;
|
||||||
|
DROP TABLE `temp_old_performers_scenes`;
|
||||||
@@ -109,6 +109,10 @@ func (qb *MovieQueryBuilder) All() ([]*Movie, error) {
|
|||||||
return qb.queryMovies(selectAll("movies")+qb.getMovieSort(nil), nil, nil)
|
return qb.queryMovies(selectAll("movies")+qb.getMovieSort(nil), nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *MovieQueryBuilder) AllSlim() ([]*Movie, error) {
|
||||||
|
return qb.queryMovies("SELECT movies.id, movies.name FROM movies "+qb.getMovieSort(nil), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *MovieQueryBuilder) Query(findFilter *FindFilterType) ([]*Movie, int) {
|
func (qb *MovieQueryBuilder) Query(findFilter *FindFilterType) ([]*Movie, int) {
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
findFilter = &FindFilterType{}
|
findFilter = &FindFilterType{}
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ func (qb *PerformerQueryBuilder) All() ([]*Performer, error) {
|
|||||||
return qb.queryPerformers(selectAll("performers")+qb.getPerformerSort(nil), nil, nil)
|
return qb.queryPerformers(selectAll("performers")+qb.getPerformerSort(nil), nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *PerformerQueryBuilder) AllSlim() ([]*Performer, error) {
|
||||||
|
return qb.queryPerformers("SELECT performers.id, performers.name, performers.gender FROM performers "+qb.getPerformerSort(nil), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *PerformerQueryBuilder) Query(performerFilter *PerformerFilterType, findFilter *FindFilterType) ([]*Performer, int) {
|
func (qb *PerformerQueryBuilder) Query(performerFilter *PerformerFilterType, findFilter *FindFilterType) ([]*Performer, int) {
|
||||||
if performerFilter == nil {
|
if performerFilter == nil {
|
||||||
performerFilter = &PerformerFilterType{}
|
performerFilter = &PerformerFilterType{}
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ func (qb *StudioQueryBuilder) All() ([]*Studio, error) {
|
|||||||
return qb.queryStudios(selectAll("studios")+qb.getStudioSort(nil), nil, nil)
|
return qb.queryStudios(selectAll("studios")+qb.getStudioSort(nil), nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *StudioQueryBuilder) AllSlim() ([]*Studio, error) {
|
||||||
|
return qb.queryStudios("SELECT studios.id, studios.name FROM studios "+qb.getStudioSort(nil), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *StudioQueryBuilder) Query(findFilter *FindFilterType) ([]*Studio, int) {
|
func (qb *StudioQueryBuilder) Query(findFilter *FindFilterType) ([]*Studio, int) {
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
findFilter = &FindFilterType{}
|
findFilter = &FindFilterType{}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func (qb *TagQueryBuilder) Create(newTag Tag, tx *sqlx.Tx) (*Tag, error) {
|
|||||||
if err := tx.Get(&newTag, `SELECT * FROM tags WHERE id = ? LIMIT 1`, studioID); err != nil {
|
if err := tx.Get(&newTag, `SELECT * FROM tags WHERE id = ? LIMIT 1`, studioID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &newTag, nil
|
return &newTag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +136,10 @@ func (qb *TagQueryBuilder) All() ([]*Tag, error) {
|
|||||||
return qb.queryTags(selectAll("tags")+qb.getTagSort(nil), nil, nil)
|
return qb.queryTags(selectAll("tags")+qb.getTagSort(nil), nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *TagQueryBuilder) AllSlim() ([]*Tag, error) {
|
||||||
|
return qb.queryTags("SELECT tags.id, tags.name FROM tags "+qb.getTagSort(nil), nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *TagQueryBuilder) Query(findFilter *FindFilterType) ([]*Tag, int) {
|
func (qb *TagQueryBuilder) Query(findFilter *FindFilterType) ([]*Tag, int) {
|
||||||
if findFilter == nil {
|
if findFilter == nil {
|
||||||
findFilter = &FindFilterType{}
|
findFilter = &FindFilterType{}
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ export const SceneMovieTable: React.FunctionComponent<IProps> = (
|
|||||||
) => {
|
) => {
|
||||||
const { data } = StashService.useAllMoviesForFilter();
|
const { data } = StashService.useAllMoviesForFilter();
|
||||||
|
|
||||||
const items = !!data && !!data.allMovies ? data.allMovies : [];
|
const items = !!data && !!data.allMoviesSlim ? data.allMoviesSlim : [];
|
||||||
let itemsFilter: ValidTypes[] = [];
|
let itemsFilter: ValidTypes[] = [];
|
||||||
|
|
||||||
if (!!props.movieSceneIndexes && !!items) {
|
if (!!props.movieSceneIndexes && !!items) {
|
||||||
props.movieSceneIndexes.forEach((index, movieId) => {
|
props.movieSceneIndexes.forEach((_index, movieId) => {
|
||||||
itemsFilter = itemsFilter.concat(items.filter((x) => x.id === movieId));
|
itemsFilter = itemsFilter.concat(items.filter((x) => x.id === movieId));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export const FilterSelect: React.FC<IFilterProps & ITypeProps> = (props) =>
|
|||||||
export const PerformerSelect: React.FC<IFilterProps> = (props) => {
|
export const PerformerSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllPerformersForFilter();
|
const { data, loading } = StashService.useAllPerformersForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allPerformers ?? [];
|
const normalizedData = data?.allPerformersSlim ?? [];
|
||||||
const items: Option[] = normalizedData.map((item) => ({
|
const items: Option[] = normalizedData.map((item) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name ?? "",
|
label: item.name ?? "",
|
||||||
@@ -216,7 +216,7 @@ export const PerformerSelect: React.FC<IFilterProps> = (props) => {
|
|||||||
export const StudioSelect: React.FC<IFilterProps> = (props) => {
|
export const StudioSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllStudiosForFilter();
|
const { data, loading } = StashService.useAllStudiosForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allStudios ?? [];
|
const normalizedData = data?.allStudiosSlim ?? [];
|
||||||
|
|
||||||
const items = (normalizedData.length > 0
|
const items = (normalizedData.length > 0
|
||||||
? [{ name: "None", id: "0" }, ...normalizedData]
|
? [{ name: "None", id: "0" }, ...normalizedData]
|
||||||
@@ -254,7 +254,7 @@ export const StudioSelect: React.FC<IFilterProps> = (props) => {
|
|||||||
export const MovieSelect: React.FC<IFilterProps> = (props) => {
|
export const MovieSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllMoviesForFilter();
|
const { data, loading } = StashService.useAllMoviesForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allMovies ?? [];
|
const normalizedData = data?.allMoviesSlim ?? [];
|
||||||
|
|
||||||
const items = (normalizedData.length > 0
|
const items = (normalizedData.length > 0
|
||||||
? [{ name: "None", id: "0" }, ...normalizedData]
|
? [{ name: "None", id: "0" }, ...normalizedData]
|
||||||
@@ -299,7 +299,7 @@ export const TagSelect: React.FC<IFilterProps> = (props) => {
|
|||||||
|
|
||||||
const selectedTags = props.ids ?? selectedIds;
|
const selectedTags = props.ids ?? selectedIds;
|
||||||
|
|
||||||
const tags = data?.allTags ?? [];
|
const tags = data?.allTagsSlim ?? [];
|
||||||
const selected = tags
|
const selected = tags
|
||||||
.filter((tag) => selectedTags.indexOf(tag.id) !== -1)
|
.filter((tag) => selectedTags.indexOf(tag.id) !== -1)
|
||||||
.map((tag) => ({ value: tag.id, label: tag.name }));
|
.map((tag) => ({ value: tag.id, label: tag.name }));
|
||||||
|
|||||||
Reference in New Issue
Block a user