Filter tag by hierarchy (#1746)

* Add API support for filtering tags by parent / children
* Add parent & child tags filters for tags to UI
* Add API support for filtering tags by parent / child count
* Add parent & child count filters for tags to UI
* Update db generator
* Add missing build tag
* Add unit tests

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
gitgiggety
2021-10-01 03:50:06 +02:00
committed by GitHub
parent df2c9e9754
commit dabf5acefe
15 changed files with 515 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
// uild ignore
// +build ignore
package main
@@ -7,6 +7,7 @@ import (
"database/sql"
"fmt"
"log"
"math"
"math/rand"
"os"
"strconv"
@@ -20,7 +21,7 @@ import (
"gopkg.in/yaml.v2"
)
const batchSize = 1000
const batchSize = 50000
// create an example database by generating a number of scenes, markers,
// performers, studios and tags, and associating between them all
@@ -41,6 +42,8 @@ var txnManager models.TransactionManager
var c *config
func main() {
rand.Seed(time.Now().UnixNano())
var err error
c, err = loadConfig()
if err != nil {
@@ -81,6 +84,7 @@ func populateDB() {
makeScenes(c.Scenes)
makeImages(c.Images)
makeGalleries(c.Galleries)
makeMarkers(c.Markers)
}
func withTxn(f func(r models.Repository) error) error {
@@ -112,8 +116,25 @@ func makeTags(n int) {
Name: name,
}
_, err := r.Tag().Create(tag)
return err
created, err := r.Tag().Create(tag)
if err != nil {
return err
}
if rand.Intn(100) > 5 {
t, _, err := r.Tag().Query(nil, getRandomFilter(1))
if err != nil {
return err
}
if len(t) > 0 && t[0].ID != created.ID {
if err := r.Tag().UpdateParentTags(created.ID, []int{t[0].ID}); err != nil {
return err
}
}
}
return nil
})
}); err != nil {
panic(err)
@@ -184,7 +205,6 @@ func makePerformers(n int) {
func makeScenes(n int) {
logger.Infof("creating %d scenes...", n)
rand.Seed(533)
for i := 0; i < n; {
// do in batches of 1000
batch := i + batchSize
@@ -259,7 +279,6 @@ func generateScene(i int) models.Scene {
func makeImages(n int) {
logger.Infof("creating %d images...", n)
rand.Seed(1293)
for i := 0; i < n; {
// do in batches of 1000
batch := i + batchSize
@@ -301,7 +320,6 @@ func generateImage(i int) models.Image {
func makeGalleries(n int) {
logger.Infof("creating %d galleries...", n)
rand.Seed(92113)
for i := 0; i < n; {
// do in batches of 1000
batch := i + batchSize
@@ -342,8 +360,48 @@ func generateGallery(i int) models.Gallery {
}
}
func makeMarkers(n int) {
logger.Infof("creating %d markers...", n)
for i := 0; i < n; {
// do in batches of 1000
batch := i + batchSize
if err := withTxn(func(r models.Repository) error {
for ; i < batch && i < n; i++ {
marker := generateMarker(i)
marker.SceneID = models.NullInt64(int64(getRandomScene()))
marker.PrimaryTagID = getRandomTags(r, 1, 1)[0]
created, err := r.SceneMarker().Create(marker)
if err != nil {
return err
}
tags := getRandomTags(r, 0, 5)
// remove primary tag
tags = utils.IntExclude(tags, []int{marker.PrimaryTagID})
if err := r.SceneMarker().UpdateTags(created.ID, tags); err != nil {
return err
}
}
logger.Infof("... created %d markers", i)
return nil
}); err != nil {
panic(err)
}
}
}
func generateMarker(i int) models.SceneMarker {
return models.SceneMarker{
Title: names[c.Naming.Scenes].generateName(rand.Intn(7) + 1),
}
}
func getRandomFilter(n int) *models.FindFilterType {
sortBy := "random"
seed := math.Floor(rand.Float64() * math.Pow10(8))
sortBy := fmt.Sprintf("random_%.f", seed)
return &models.FindFilterType{
Sort: &sortBy,
PerPage: &n,
@@ -368,7 +426,7 @@ func getRandomStudioID(r models.Repository) sql.NullInt64 {
func makeSceneRelationships(r models.Repository, id int) {
// add tags
tagIDs := getRandomTags(r)
tagIDs := getRandomTags(r, 0, 15)
if len(tagIDs) > 0 {
if err := r.Scene().UpdateTags(id, tagIDs); err != nil {
panic(err)
@@ -385,26 +443,33 @@ func makeSceneRelationships(r models.Repository, id int) {
}
func makeImageRelationships(r models.Repository, id int) {
// there are typically many more images. For performance reasons
// only a small proportion should have tags/performers
// add tags
tagIDs := getRandomTags(r)
if len(tagIDs) > 0 {
if err := r.Image().UpdateTags(id, tagIDs); err != nil {
panic(err)
if rand.Intn(100) == 0 {
tagIDs := getRandomTags(r, 1, 15)
if len(tagIDs) > 0 {
if err := r.Image().UpdateTags(id, tagIDs); err != nil {
panic(err)
}
}
}
// add performers
performerIDs := getRandomPerformers(r)
if len(tagIDs) > 0 {
if err := r.Image().UpdatePerformers(id, performerIDs); err != nil {
panic(err)
if rand.Intn(100) <= 1 {
performerIDs := getRandomPerformers(r)
if len(performerIDs) > 0 {
if err := r.Image().UpdatePerformers(id, performerIDs); err != nil {
panic(err)
}
}
}
}
func makeGalleryRelationships(r models.Repository, id int) {
// add tags
tagIDs := getRandomTags(r)
tagIDs := getRandomTags(r, 0, 15)
if len(tagIDs) > 0 {
if err := r.Gallery().UpdateTags(id, tagIDs); err != nil {
panic(err)
@@ -450,8 +515,17 @@ func getRandomPerformers(r models.Repository) []int {
return ret
}
func getRandomTags(r models.Repository) []int {
n := rand.Intn(15)
func getRandomScene() int {
return rand.Intn(c.Scenes) + 1
}
func getRandomTags(r models.Repository, min, max int) []int {
var n int
if min == max {
n = min
} else {
n = rand.Intn(max-min) + min
}
var ret []int
// if n > 0 {