GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

78 lines
1.7 KiB

package mongodb
import (
"context"
"sort"
"strings"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/repositories"
"github.com/globalsign/mgo"
"go.mongodb.org/mongo-driver/bson"
)
type tagRepository struct {
stories *mgo.Collection
}
func newTagRepository(db *mgo.Database) repositories.TagRepository {
return &tagRepository{
stories: db.C("story.stories"),
}
}
func (r *tagRepository) Find(ctx context.Context, kind models.TagKind, name string) (*models.Tag, error) {
tags := make([]*models.Tag, 0, 1)
err := r.stories.Find(bson.M{"listed": true, "tags": bson.M{"kind": kind, "name": name}}).Distinct("tag", &tags)
if err != nil {
return nil, err
} else if len(tags) == 0 {
return nil, repositories.ErrNotFound
}
for _, tag := range tags {
if tag.Kind == kind && tag.Name == name {
return tag, nil
}
}
return nil, repositories.ErrNotFound
}
func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
tags := make([]*models.Tag, 0, 64)
query := bson.M{"listed": true, "tags": bson.M{"$ne": nil}}
if filter.Kind != nil {
query["tags.kind"] = *filter.Kind
}
err := r.stories.Find(query).Distinct("tags", &tags)
if err != nil {
return nil, err
}
if filter.Kind != nil {
// While it's unsorted, delete any incorrect tags with replacement.
for i := 0; i < len(tags); i++ {
if tags[i].Kind != *filter.Kind {
tags[i] = tags[len(tags)-1]
tags = tags[:len(tags)-1]
i--
}
}
}
sort.Slice(tags, func(i, j int) bool {
if filter.Kind == nil {
kindCmp := strings.Compare(string(tags[i].Kind), string(tags[j].Kind))
if kindCmp != 0 {
return kindCmp < 0
}
}
return strings.Compare(tags[i].Name, tags[j].Name) < 0
})
return tags, nil
}