mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Add O-Counter for Performers and Sort/Filter Performers by O-Counter (#3588)
* initial commit of sort performer by o-count * work on o_counter filter * filter working * sorting, filtering using combined scene+image count * linting * fix performer list view --------- Co-authored-by: jpnsfw <none@none.com>
This commit is contained in:
@@ -722,6 +722,28 @@ func (m *countCriterionHandlerBuilder) handler(criterion *models.IntCriterionInp
|
||||
}
|
||||
}
|
||||
|
||||
type joinedMultiSumCriterionHandlerBuilder struct {
|
||||
primaryTable string
|
||||
foreignTable1 string
|
||||
joinTable1 string
|
||||
foreignTable2 string
|
||||
joinTable2 string
|
||||
primaryFK string
|
||||
foreignFK1 string
|
||||
foreignFK2 string
|
||||
sum string
|
||||
}
|
||||
|
||||
func (m *joinedMultiSumCriterionHandlerBuilder) handler(criterion *models.IntCriterionInput) criterionHandlerFunc {
|
||||
return func(ctx context.Context, f *filterBuilder) {
|
||||
if criterion != nil {
|
||||
clause, args := getJoinedMultiSumCriterionClause(m.primaryTable, m.foreignTable1, m.joinTable1, m.foreignTable2, m.joinTable2, m.primaryFK, m.foreignFK1, m.foreignFK2, m.sum, *criterion)
|
||||
|
||||
f.addWhere(clause, args...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handler for StringCriterion for string list fields
|
||||
type stringListCriterionHandlerBuilder struct {
|
||||
// table joining primary and foreign objects
|
||||
|
||||
@@ -513,6 +513,19 @@ func (qb *ImageStore) CountByGalleryID(ctx context.Context, galleryID int) (int,
|
||||
return count(ctx, q)
|
||||
}
|
||||
|
||||
func (qb *ImageStore) OCountByPerformerID(ctx context.Context, performerID int) (int, error) {
|
||||
table := qb.table()
|
||||
joinTable := performersImagesJoinTable
|
||||
q := dialect.Select(goqu.COALESCE(goqu.SUM("o_counter"), 0)).From(table).InnerJoin(joinTable, goqu.On(table.Col(idColumn).Eq(joinTable.Col(imageIDColumn)))).Where(joinTable.Col(performerIDColumn).Eq(performerID))
|
||||
|
||||
var ret int
|
||||
if err := querySimple(ctx, q, &ret); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *ImageStore) FindByFolderID(ctx context.Context, folderID file.FolderID) ([]*models.Image, error) {
|
||||
table := qb.table()
|
||||
fileTable := goqu.T(fileTable)
|
||||
|
||||
@@ -629,6 +629,7 @@ func (qb *PerformerStore) makeFilter(ctx context.Context, filter *models.Perform
|
||||
query.handleCriterion(ctx, performerSceneCountCriterionHandler(qb, filter.SceneCount))
|
||||
query.handleCriterion(ctx, performerImageCountCriterionHandler(qb, filter.ImageCount))
|
||||
query.handleCriterion(ctx, performerGalleryCountCriterionHandler(qb, filter.GalleryCount))
|
||||
query.handleCriterion(ctx, performerOCounterCriterionHandler(qb, filter.OCounter))
|
||||
query.handleCriterion(ctx, dateCriterionHandler(filter.Birthdate, tableName+".birthdate"))
|
||||
query.handleCriterion(ctx, dateCriterionHandler(filter.DeathDate, tableName+".death_date"))
|
||||
query.handleCriterion(ctx, timestampCriterionHandler(filter.CreatedAt, tableName+".created_at"))
|
||||
@@ -805,6 +806,22 @@ func performerGalleryCountCriterionHandler(qb *PerformerStore, count *models.Int
|
||||
return h.handler(count)
|
||||
}
|
||||
|
||||
func performerOCounterCriterionHandler(qb *PerformerStore, count *models.IntCriterionInput) criterionHandlerFunc {
|
||||
h := joinedMultiSumCriterionHandlerBuilder{
|
||||
primaryTable: performerTable,
|
||||
foreignTable1: sceneTable,
|
||||
joinTable1: performersScenesTable,
|
||||
foreignTable2: imageTable,
|
||||
joinTable2: performersImagesTable,
|
||||
primaryFK: performerIDColumn,
|
||||
foreignFK1: sceneIDColumn,
|
||||
foreignFK2: imageIDColumn,
|
||||
sum: "o_counter",
|
||||
}
|
||||
|
||||
return h.handler(count)
|
||||
}
|
||||
|
||||
func performerStudiosCriterionHandler(qb *PerformerStore, studios *models.HierarchicalMultiCriterionInput) criterionHandlerFunc {
|
||||
return func(ctx context.Context, f *filterBuilder) {
|
||||
if studios != nil {
|
||||
@@ -906,6 +923,9 @@ func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) st
|
||||
default:
|
||||
sortQuery += getSort(sort, direction, "performers")
|
||||
}
|
||||
if sort == "o_counter" {
|
||||
return getMultiSumSort("o_counter", performerTable, sceneTable, performersScenesTable, imageTable, performersImagesTable, performerIDColumn, sceneIDColumn, imageIDColumn, direction)
|
||||
}
|
||||
|
||||
// Whatever the sorting, always use name/id as a final sort
|
||||
sortQuery += ", COALESCE(performers.name, performers.id) COLLATE NATURAL_CI ASC"
|
||||
|
||||
@@ -680,6 +680,19 @@ func (qb *SceneStore) CountByPerformerID(ctx context.Context, performerID int) (
|
||||
return count(ctx, q)
|
||||
}
|
||||
|
||||
func (qb *SceneStore) OCountByPerformerID(ctx context.Context, performerID int) (int, error) {
|
||||
table := qb.table()
|
||||
joinTable := scenesPerformersJoinTable
|
||||
|
||||
q := dialect.Select(goqu.COALESCE(goqu.SUM("o_counter"), 0)).From(table).InnerJoin(joinTable, goqu.On(table.Col(idColumn).Eq(joinTable.Col(sceneIDColumn)))).Where(joinTable.Col(performerIDColumn).Eq(performerID))
|
||||
var ret int
|
||||
if err := querySimple(ctx, q, &ret); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (qb *SceneStore) FindByMovieID(ctx context.Context, movieID int) ([]*models.Scene, error) {
|
||||
sq := dialect.From(scenesMoviesJoinTable).Select(scenesMoviesJoinTable.Col(sceneIDColumn)).Where(
|
||||
scenesMoviesJoinTable.Col(movieIDColumn).Eq(movieID),
|
||||
|
||||
@@ -103,6 +103,27 @@ func getCountSort(primaryTable, joinTable, primaryFK, direction string) string {
|
||||
return fmt.Sprintf(" ORDER BY (SELECT COUNT(*) FROM %s WHERE %s = %s.id) %s", joinTable, primaryFK, primaryTable, getSortDirection(direction))
|
||||
}
|
||||
|
||||
func getMultiSumSort(sum string, primaryTable, foreignTable1, joinTable1, foreignTable2, joinTable2, primaryFK, foreignFK1, foreignFK2, direction string) string {
|
||||
return fmt.Sprintf(" ORDER BY (SELECT SUM(%s) "+
|
||||
"FROM ("+
|
||||
"SELECT SUM(%s) as %s from %s s "+
|
||||
"LEFT JOIN %s ON %s.id = s.%s "+
|
||||
"WHERE s.%s = %s.id "+
|
||||
"UNION ALL "+
|
||||
"SELECT SUM(%s) as %s from %s s "+
|
||||
"LEFT JOIN %s ON %s.id = s.%s "+
|
||||
"WHERE s.%s = %s.id "+
|
||||
")) %s",
|
||||
sum,
|
||||
sum, sum, joinTable1,
|
||||
foreignTable1, foreignTable1, foreignFK1,
|
||||
primaryFK, primaryTable,
|
||||
sum, sum, joinTable2,
|
||||
foreignTable2, foreignTable2, foreignFK2,
|
||||
primaryFK, primaryTable,
|
||||
getSortDirection(direction))
|
||||
}
|
||||
|
||||
func getStringSearchClause(columns []string, q string, not bool) sqlClause {
|
||||
var likeClauses []string
|
||||
var args []interface{}
|
||||
@@ -287,6 +308,28 @@ func getCountCriterionClause(primaryTable, joinTable, primaryFK string, criterio
|
||||
return getIntCriterionWhereClause(lhs, criterion)
|
||||
}
|
||||
|
||||
func getJoinedMultiSumCriterionClause(primaryTable, foreignTable1, joinTable1, foreignTable2, joinTable2, primaryFK string, foreignFK1 string, foreignFK2 string, sum string, criterion models.IntCriterionInput) (string, []interface{}) {
|
||||
lhs := fmt.Sprintf("(SELECT SUM(%s) "+
|
||||
"FROM ("+
|
||||
"SELECT SUM(%s) as %s from %s s "+
|
||||
"LEFT JOIN %s ON %s.id = s.%s "+
|
||||
"WHERE s.%s = %s.id "+
|
||||
"UNION ALL "+
|
||||
"SELECT SUM(%s) as %s from %s s "+
|
||||
"LEFT JOIN %s ON %s.id = s.%s "+
|
||||
"WHERE s.%s = %s.id "+
|
||||
"))",
|
||||
sum,
|
||||
sum, sum, joinTable1,
|
||||
foreignTable1, foreignTable1, foreignFK1,
|
||||
primaryFK, primaryTable,
|
||||
sum, sum, joinTable2,
|
||||
foreignTable2, foreignTable2, foreignFK2,
|
||||
primaryFK, primaryTable,
|
||||
)
|
||||
return getIntCriterionWhereClause(lhs, criterion)
|
||||
}
|
||||
|
||||
func coalesce(column string) string {
|
||||
return fmt.Sprintf("COALESCE(%s, '')", column)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user