mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01: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:
parent
ac41416cd7
commit
9d641c64e3
4 changed files with 42 additions and 46 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
### ✨ New Features
|
||||
* Added filtering and sorting on scene marker count for tags. ([#1603](https://github.com/stashapp/stash/pull/1603))
|
||||
* Support excluding fields and editing tags when saving from scene tagger view. ([#1605](https://github.com/stashapp/stash/pull/1605))
|
||||
* Added not equals/greater than/less than modifiers for resolution criteria. ([#1568](https://github.com/stashapp/stash/pull/1568))
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,7 @@ import { ListFilterOptions } from "./filter-options";
|
|||
import { DisplayMode } from "./types";
|
||||
|
||||
const defaultSortBy = "name";
|
||||
// scene markers count has been disabled for now due to performance
|
||||
// issues
|
||||
const sortByOptions = [
|
||||
"name",
|
||||
"random",
|
||||
/* "scene_markers_count" */
|
||||
]
|
||||
const sortByOptions = ["name", "random"]
|
||||
.map(ListFilterOptions.createSortBy)
|
||||
.concat([
|
||||
{
|
||||
|
|
@ -33,6 +27,10 @@ const sortByOptions = [
|
|||
messageID: "scene_count",
|
||||
value: "scenes_count",
|
||||
},
|
||||
{
|
||||
messageID: "marker_count",
|
||||
value: "scene_markers_count",
|
||||
},
|
||||
]);
|
||||
|
||||
const displayModeOptions = [DisplayMode.Grid, DisplayMode.List];
|
||||
|
|
@ -44,8 +42,7 @@ const criterionOptions = [
|
|||
createMandatoryNumberCriterionOption("image_count"),
|
||||
createMandatoryNumberCriterionOption("gallery_count"),
|
||||
createMandatoryNumberCriterionOption("performer_count"),
|
||||
// marker count has been disabled for now due to performance issues
|
||||
// ListFilterModel.createCriterionOption("marker_count"),
|
||||
createMandatoryNumberCriterionOption("marker_count"),
|
||||
];
|
||||
|
||||
export const TagListFilterOptions = new ListFilterOptions(
|
||||
|
|
|
|||
Loading…
Reference in a new issue