mirror of
https://github.com/stashapp/stash.git
synced 2025-12-08 01:13:09 +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))
|
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(stringCriterionHandler(tagFilter.Name, tagTable+".name"))
|
||||||
query.handleCriterion(tagAliasCriterionHandler(qb, tagFilter.Aliases))
|
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(tagImageCountCriterionHandler(qb, tagFilter.ImageCount))
|
||||||
query.handleCriterion(tagGalleryCountCriterionHandler(qb, tagFilter.GalleryCount))
|
query.handleCriterion(tagGalleryCountCriterionHandler(qb, tagFilter.GalleryCount))
|
||||||
query.handleCriterion(tagPerformerCountCriterionHandler(qb, tagFilter.PerformerCount))
|
query.handleCriterion(tagPerformerCountCriterionHandler(qb, tagFilter.PerformerCount))
|
||||||
|
query.handleCriterion(tagMarkerCountCriterionHandler(qb, tagFilter.MarkerCount))
|
||||||
|
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
@ -303,19 +296,6 @@ func (qb *tagQueryBuilder) Query(tagFilter *models.TagFilterType, findFilter *mo
|
||||||
|
|
||||||
query.body = selectDistinctIDs(tagTable)
|
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 != "" {
|
if q := findFilter.Q; q != nil && *q != "" {
|
||||||
query.join(tagAliasesTable, "", "tag_aliases.tag_id = tags.id")
|
query.join(tagAliasesTable, "", "tag_aliases.tag_id = tags.id")
|
||||||
searchColumns := []string{"tags.name", "tag_aliases.alias"}
|
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 {
|
func (qb *tagQueryBuilder) getDefaultTagSort() string {
|
||||||
return getSort("name", "ASC", "tags")
|
return getSort("name", "ASC", "tags")
|
||||||
}
|
}
|
||||||
|
|
@ -459,6 +456,9 @@ func (qb *tagQueryBuilder) getTagSort(query *queryBuilder, findFilter *models.Fi
|
||||||
case "scenes_count":
|
case "scenes_count":
|
||||||
query.join("scenes_tags", "", "scenes_tags.tag_id = tags.id")
|
query.join("scenes_tags", "", "scenes_tags.tag_id = tags.id")
|
||||||
return " ORDER BY COUNT(distinct scenes_tags.scene_id) " + direction
|
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":
|
case "images_count":
|
||||||
query.join("images_tags", "", "images_tags.tag_id = tags.id")
|
query.join("images_tags", "", "images_tags.tag_id = tags.id")
|
||||||
return " ORDER BY COUNT(distinct images_tags.image_id) " + direction
|
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) {
|
verifyTagMarkerCount(t, countCriterion)
|
||||||
// countCriterion := models.IntCriterionInput{
|
|
||||||
// Value: 1,
|
|
||||||
// Modifier: models.CriterionModifierEquals,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// verifyTagMarkerCount(t, countCriterion)
|
countCriterion.Modifier = models.CriterionModifierNotEquals
|
||||||
|
verifyTagMarkerCount(t, countCriterion)
|
||||||
|
|
||||||
// countCriterion.Modifier = models.CriterionModifierNotEquals
|
countCriterion.Modifier = models.CriterionModifierLessThan
|
||||||
// verifyTagMarkerCount(t, countCriterion)
|
verifyTagMarkerCount(t, countCriterion)
|
||||||
|
|
||||||
// countCriterion.Modifier = models.CriterionModifierLessThan
|
countCriterion.Value = 0
|
||||||
// verifyTagMarkerCount(t, countCriterion)
|
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) {
|
func verifyTagMarkerCount(t *testing.T, markerCountCriterion models.IntCriterionInput) {
|
||||||
withTxn(func(r models.Repository) error {
|
withTxn(func(r models.Repository) error {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
### ✨ New Features
|
### ✨ 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))
|
* 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))
|
* 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";
|
import { DisplayMode } from "./types";
|
||||||
|
|
||||||
const defaultSortBy = "name";
|
const defaultSortBy = "name";
|
||||||
// scene markers count has been disabled for now due to performance
|
const sortByOptions = ["name", "random"]
|
||||||
// issues
|
|
||||||
const sortByOptions = [
|
|
||||||
"name",
|
|
||||||
"random",
|
|
||||||
/* "scene_markers_count" */
|
|
||||||
]
|
|
||||||
.map(ListFilterOptions.createSortBy)
|
.map(ListFilterOptions.createSortBy)
|
||||||
.concat([
|
.concat([
|
||||||
{
|
{
|
||||||
|
|
@ -33,6 +27,10 @@ const sortByOptions = [
|
||||||
messageID: "scene_count",
|
messageID: "scene_count",
|
||||||
value: "scenes_count",
|
value: "scenes_count",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
messageID: "marker_count",
|
||||||
|
value: "scene_markers_count",
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const displayModeOptions = [DisplayMode.Grid, DisplayMode.List];
|
const displayModeOptions = [DisplayMode.Grid, DisplayMode.List];
|
||||||
|
|
@ -44,8 +42,7 @@ const criterionOptions = [
|
||||||
createMandatoryNumberCriterionOption("image_count"),
|
createMandatoryNumberCriterionOption("image_count"),
|
||||||
createMandatoryNumberCriterionOption("gallery_count"),
|
createMandatoryNumberCriterionOption("gallery_count"),
|
||||||
createMandatoryNumberCriterionOption("performer_count"),
|
createMandatoryNumberCriterionOption("performer_count"),
|
||||||
// marker count has been disabled for now due to performance issues
|
createMandatoryNumberCriterionOption("marker_count"),
|
||||||
// ListFilterModel.createCriterionOption("marker_count"),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export const TagListFilterOptions = new ListFilterOptions(
|
export const TagListFilterOptions = new ListFilterOptions(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue