This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.aiterp.net/rpdata/api/database/mongodb"
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
)
|
||||
|
||||
// ErrDriverUnrecognized is returned if the driver is not recognized
|
||||
var ErrDriverUnrecognized = errors.New("Driver not recognized, check your config or update rpdata")
|
||||
|
||||
// Init sets up the database.
|
||||
func Init(config config.Database) (bundle *repositories.Bundle, closeFn func() error, err error) {
|
||||
switch config.Driver {
|
||||
case "mongo", "mgo", "mongodb":
|
||||
return mongodb.Init(config)
|
||||
default:
|
||||
return nil, nil, ErrDriverUnrecognized
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
// Init initializes the mongodb database
|
||||
func Init(cfg config.Database) (bundle *repositories.Bundle, closeFn func() error, err error) {
|
||||
port := cfg.Port
|
||||
if port <= 0 {
|
||||
port = 27017
|
||||
}
|
||||
|
||||
session, err := mgo.DialWithInfo(&mgo.DialInfo{
|
||||
Addrs: []string{fmt.Sprintf("%s:%d", cfg.Host, port)},
|
||||
Timeout: 30 * time.Second,
|
||||
Database: cfg.Db,
|
||||
Username: cfg.Username,
|
||||
Password: cfg.Password,
|
||||
Mechanism: cfg.Mechanism,
|
||||
Source: cfg.Db,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
db := session.DB(cfg.Db)
|
||||
|
||||
bundle = &repositories.Bundle{
|
||||
Tags: newTagRepository(db),
|
||||
}
|
||||
|
||||
closeFn = func() error {
|
||||
session.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
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, 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
|
||||
}
|
||||
|
||||
return tags[0], nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user