mirror of
https://github.com/stashapp/stash.git
synced 2026-05-08 18:10:36 -05:00
Actually implement TagFilter.marker_count (#1603)
* Actually implement TagFilter.marker_count
The marker_count filter/criterion as defined in TagFilterType isn't
actually implemented. This adds an implementation for it.
Do note this implementation _might_ have performance issues because of
using OR (in the join). Another implentation would be to remove both
joins and use:
```SQL
COUNT(
SELECT id FROM scene_markers WHERE primary_tag_id = tags.id
UNION
SELECT scene_marker_id FROM scene_markers_tags WHERE tag_id = tags.id
)
```
Note this doesn't require a DISTINCT as UNION already removes any
duplicate records.
* Restore marker count filter and sorting
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
+21
-21
@@ -271,14 +271,6 @@ func (qb *tagQueryBuilder) makeFilter(tagFilter *models.TagFilterType) *filterBu
|
||||
query.not(qb.makeFilter(tagFilter.Not))
|
||||
}
|
||||
|
||||
// if markerCount := tagFilter.MarkerCount; markerCount != nil {
|
||||
// clause, count := getIntCriterionWhereClause("count(distinct scene_markers.id)", *markerCount)
|
||||
// query.addHaving(clause)
|
||||
// if count == 1 {
|
||||
// query.addArg(markerCount.Value)
|
||||
// }
|
||||
// }
|
||||
|
||||
query.handleCriterion(stringCriterionHandler(tagFilter.Name, tagTable+".name"))
|
||||
query.handleCriterion(tagAliasCriterionHandler(qb, tagFilter.Aliases))
|
||||
|
||||
@@ -287,6 +279,7 @@ func (qb *tagQueryBuilder) makeFilter(tagFilter *models.TagFilterType) *filterBu
|
||||
query.handleCriterion(tagImageCountCriterionHandler(qb, tagFilter.ImageCount))
|
||||
query.handleCriterion(tagGalleryCountCriterionHandler(qb, tagFilter.GalleryCount))
|
||||
query.handleCriterion(tagPerformerCountCriterionHandler(qb, tagFilter.PerformerCount))
|
||||
query.handleCriterion(tagMarkerCountCriterionHandler(qb, tagFilter.MarkerCount))
|
||||
|
||||
return query
|
||||
}
|
||||
@@ -303,19 +296,6 @@ func (qb *tagQueryBuilder) Query(tagFilter *models.TagFilterType, findFilter *mo
|
||||
|
||||
query.body = selectDistinctIDs(tagTable)
|
||||
|
||||
/*
|
||||
query.body += `
|
||||
left join tags_image on tags_image.tag_id = tags.id
|
||||
left join scenes_tags on scenes_tags.tag_id = tags.id
|
||||
left join scene_markers_tags on scene_markers_tags.tag_id = tags.id
|
||||
left join scene_markers on scene_markers.primary_tag_id = tags.id OR scene_markers.id = scene_markers_tags.scene_marker_id
|
||||
left join scenes on scenes_tags.scene_id = scenes.id`
|
||||
*/
|
||||
|
||||
// the presence of joining on scene_markers.primary_tag_id and scene_markers_tags.tag_id
|
||||
// appears to confuse sqlite and causes serious performance issues.
|
||||
// Disabling querying/sorting on marker count for now.
|
||||
|
||||
if q := findFilter.Q; q != nil && *q != "" {
|
||||
query.join(tagAliasesTable, "", "tag_aliases.tag_id = tags.id")
|
||||
searchColumns := []string{"tags.name", "tag_aliases.alias"}
|
||||
@@ -439,6 +419,23 @@ func tagPerformerCountCriterionHandler(qb *tagQueryBuilder, performerCount *mode
|
||||
}
|
||||
}
|
||||
|
||||
func tagMarkerCountCriterionHandler(qb *tagQueryBuilder, markerCount *models.IntCriterionInput) criterionHandlerFunc {
|
||||
return func(f *filterBuilder) {
|
||||
if markerCount != nil {
|
||||
f.addJoin("scene_markers_tags", "", "scene_markers_tags.tag_id = tags.id")
|
||||
f.addJoin("scene_markers", "", "scene_markers_tags.scene_marker_id = scene_markers.id OR scene_markers.primary_tag_id = tags.id")
|
||||
clause, count := getIntCriterionWhereClause("count(distinct scene_markers.id)", *markerCount)
|
||||
|
||||
args := []interface{}{}
|
||||
if count == 1 {
|
||||
args = append(args, markerCount.Value)
|
||||
}
|
||||
|
||||
f.addHaving(clause, args...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (qb *tagQueryBuilder) getDefaultTagSort() string {
|
||||
return getSort("name", "ASC", "tags")
|
||||
}
|
||||
@@ -459,6 +456,9 @@ func (qb *tagQueryBuilder) getTagSort(query *queryBuilder, findFilter *models.Fi
|
||||
case "scenes_count":
|
||||
query.join("scenes_tags", "", "scenes_tags.tag_id = tags.id")
|
||||
return " ORDER BY COUNT(distinct scenes_tags.scene_id) " + direction
|
||||
case "scene_markers_count":
|
||||
query.join("scene_markers_tags", "", "scene_markers_tags.tag_id = tags.id")
|
||||
return " ORDER BY COUNT(distinct scene_markers_tags.scene_marker_id) " + direction
|
||||
case "images_count":
|
||||
query.join("images_tags", "", "images_tags.tag_id = tags.id")
|
||||
return " ORDER BY COUNT(distinct images_tags.image_id) " + direction
|
||||
|
||||
+14
-16
@@ -320,26 +320,24 @@ func verifyTagSceneCount(t *testing.T, sceneCountCriterion models.IntCriterionIn
|
||||
})
|
||||
}
|
||||
|
||||
// disabled due to performance issues
|
||||
func TestTagQueryMarkerCount(t *testing.T) {
|
||||
countCriterion := models.IntCriterionInput{
|
||||
Value: 1,
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
}
|
||||
|
||||
// func TestTagQueryMarkerCount(t *testing.T) {
|
||||
// countCriterion := models.IntCriterionInput{
|
||||
// Value: 1,
|
||||
// Modifier: models.CriterionModifierEquals,
|
||||
// }
|
||||
verifyTagMarkerCount(t, countCriterion)
|
||||
|
||||
// verifyTagMarkerCount(t, countCriterion)
|
||||
countCriterion.Modifier = models.CriterionModifierNotEquals
|
||||
verifyTagMarkerCount(t, countCriterion)
|
||||
|
||||
// countCriterion.Modifier = models.CriterionModifierNotEquals
|
||||
// verifyTagMarkerCount(t, countCriterion)
|
||||
countCriterion.Modifier = models.CriterionModifierLessThan
|
||||
verifyTagMarkerCount(t, countCriterion)
|
||||
|
||||
// countCriterion.Modifier = models.CriterionModifierLessThan
|
||||
// verifyTagMarkerCount(t, countCriterion)
|
||||
|
||||
// countCriterion.Value = 0
|
||||
// countCriterion.Modifier = models.CriterionModifierGreaterThan
|
||||
// verifyTagMarkerCount(t, countCriterion)
|
||||
// }
|
||||
countCriterion.Value = 0
|
||||
countCriterion.Modifier = models.CriterionModifierGreaterThan
|
||||
verifyTagMarkerCount(t, countCriterion)
|
||||
}
|
||||
|
||||
func verifyTagMarkerCount(t *testing.T, markerCountCriterion models.IntCriterionInput) {
|
||||
withTxn(func(r models.Repository) error {
|
||||
|
||||
Reference in New Issue
Block a user