I am using following go file as layer between my http API and mgo:
package store
import (
"reflect"
"strings"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
)
type Manager struct {
collection *mgo.Collection
}
type Model interface {
Id() bson.ObjectId
}
func (m *Manager) index(model Model) {
v := reflect.ValueOf(model).Elem()
var index, unique []string
for i := 0; i < v.NumField(); i++ {
t := v.Type().Field(i)
if s := t.Tag.Get("store"); len(s) != 0 {
if strings.Contains(s, "index") {
index = append(index, t.Name)
}
if strings.Contains(s, "unique") {
unique = append(unique, t.Name)
}
}
}
m.collection.EnsureIndex(mgo.Index{Key: index})
m.collection.EnsureIndex(mgo.Index{Key: unique, Unique: true})
}
func (m *Manager) Create(model Model) error {
m.index(model)
return m.collection.Insert(model)
}
func (m *Manager) Update(model Model) error {
m.index(model)
return m.collection.UpdateId(model.Id(), model)
}
func (m *Manager) Destroy(model Model) error {
m.index(model)
return m.collection.RemoveId(model.Id())
}
func (m *Manager) Find(query Query, models interface{}) error {
return m.collection.Find(query).All(models)
}
func (m *Manager) FindOne(query Query, model Model) error {
m.index(model)
return m.collection.Find(query).One(model)
}
As you see I am ensuring indices on each operation by calling m.index(model)
. The model type has tags of form store:"index"
or store:"unique"
.
As setting a general index is different from setting a unique index I collect them separately and then call m.collection.EnsureIndex
on the resolved keys.
However the second call to m.collection.EnsureIndex
does never reach the server only the normal indices were sent.
A look into the godocs shows that ensure Index caches its calls so I think I should combine them in one call.
So how do I combine different index settings in one call to EnsureIndex?
Solution: You need to lower case field names from reflect to use them with mgo...