mgocrud/setup.go

122 lines
2.8 KiB
Go

package mgocrud
import (
"fmt"
"reflect"
"strings"
mgo "gopkg.in/mgo.v2"
)
// EnsureIndex ensured mongodb index reflecting model struct index tag
func (db *MgoDatabase) EnsureIndex(m ModelInterface, index ...Index) error {
colName := GetCollectionName(m)
col := db.C(colName)
if len(index) > 0 {
// only ensure given index
for _, i := range index {
err := col.EnsureIndex(i)
if err != nil {
return err
}
}
return nil
}
// ensure index by struct fields
mType := reflect.TypeOf(m)
textFields := []string{}
var _indexWalk func(t reflect.Type, fieldbase string) error
_indexWalk = func(t reflect.Type, fieldbase string) error {
for i := 0; i < 2; i++ {
if t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice {
t = t.Elem()
}
}
if t.Kind() == reflect.Struct {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
indexTag := field.Tag.Get("index")
bsonField := strings.Split(field.Tag.Get("bson"), ",")[0]
if bsonField == "" {
bsonField = strings.ToLower(field.Name)
}
if bsonField != "-" {
if indexTag != "" {
index := mgo.Index{
Background: false,
Sparse: false,
Unique: false,
}
for _, indexEl := range strings.Split(indexTag, ",") {
switch {
case indexEl == "single":
index.Key = []string{fieldbase + bsonField}
case indexEl == "unique":
index.Unique = true
case indexEl == "sparse":
index.Sparse = true
case indexEl == "background":
index.Background = true
case indexEl == "text":
textFields = append(textFields, "$text:"+fieldbase+bsonField)
default:
return fmt.Errorf("invalid index tag on collection %s.%s for field %s%s in model %+v", db.Name(), colName, fieldbase, bsonField, t)
}
}
if len(index.Key) > 0 {
// fmt.Println(bsonField, index)
fmt.Printf("ensure index on collection %s.%s for field %s%s\n", db.Name(), colName, fieldbase, bsonField)
err := col.EnsureIndex(NewMgoIndex(index))
if err != nil {
return err
}
}
}
fBase := bsonField + "."
if field.Anonymous {
fBase = ""
}
err := _indexWalk(field.Type, fBase)
if err != nil {
return err
}
}
}
}
return nil
}
err := _indexWalk(mType, "")
if err != nil {
return err
}
if len(textFields) > 0 {
// fmt.Println("$text", textFields)
fmt.Printf("ensure text index on collection %s.%s for fields %v\n", db.Name(), GetCollectionName(m), textFields)
err := col.EnsureIndex(NewMgoIndex(mgo.Index{
Name: "textindex",
Key: textFields,
DefaultLanguage: "german",
Background: false,
}))
if err != nil {
return err
}
}
return nil
}