func parseIndexKey(spec string) string {
	keyAndDirection := strings.Split(spec, "_")
	if len(keyAndDirection) != 2 {
		return ""
	}
	direction := ""
	if keyAndDirection[1] == "-1" {
		direction = "-"
	}
	return fmt.Sprintf("%s%s", direction, keyAndDirection[0])
}
parseIndexKey converts the standard mongo index key format: "<key>_(-)1"
to the format used by mgo.Index: "(-)<key>"
package server
import (
	"bufio"
	"errors"
	"fmt"
	"log"
	"os"
	"strings"
	"time"
	"gopkg.in/mgo.v2"
)
type IndexMap map[string][]*mgo.Index
func ConfigureIndexes(ms *MasterSession, config Config) {
	var err error
	worker := ms.GetWorkerSession()
	defer worker.Close()
	worker.SetTimeout(5 * time.Minute)  
	f, err := os.Open(config.IndexConfigPath)
	if err != nil {
		log.Println("[WARNING] Could not find indexes configuration file")
		return
	}
	defer f.Close()
	var indexMap = make(IndexMap)
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line != "" && !strings.HasPrefix(line, "#") {
			collectionName, index, err := parseIndex(line)
			if err != nil {
				log.Printf("[WARNING] %s\n", err.Error())
				continue
			}
			indexMap[collectionName] = append(indexMap[collectionName], index)
		}
	}
	for k := range indexMap {
		collection := worker.DB().C(k)
		for _, index := range indexMap[k] {
			log.Printf("Ensuring index: %s.%s: %s\n", config.DatabaseName, k, sprintIndexKeys(index))
			err = collection.EnsureIndex(*index)
			if err != nil {
				log.Printf("[WARNING] Could not ensure index: %s.%s: %s\n", config.DatabaseName, k, sprintIndexKeys(index))
			}
		}
	}
}
func parseIndex(line string) (collectionName string, newIndex *mgo.Index, err error) {
	config := strings.SplitN(line, ".", 2)
	if len(config) < 2 {
		return "", nil, newParseIndexError(line, "Not of format <collection_name>.<index(es)>")
	}
	collectionName = config[0]
	if len(collectionName) == 0 {
		return "", nil, newParseIndexError(line, "No collection name given")
	}
	indexSpec := config[1]
	if len(indexSpec) == 0 {
		return "", nil, newParseIndexError(line, "No index key(s) given")
	}
	if string(indexSpec[0]) == "(" {
		newIndex, err = parseCompoundIndex(indexSpec)
	} else {
		newIndex, err = parseStandardIndex(indexSpec)
	}
	if err != nil {
		return "", nil, newParseIndexError(line, err.Error())
	}
	newIndex.Background = true
	return collectionName, newIndex, nil
}
func parseStandardIndex(indexSpec string) (*mgo.Index, error) {
	key := parseIndexKey(indexSpec)
	if key == "" {
		return nil, errors.New("Standard key not of format: <key>_(-)1")
	}
	return &mgo.Index{
		Key: []string{key},
	}, nil
}
func parseCompoundIndex(indexSpec string) (*mgo.Index, error) {
	if !strings.HasPrefix(indexSpec, "(") || !strings.HasSuffix(indexSpec, ")") {
		return nil, errors.New("Compound key not of format: (<key1>_(-)1, <key2>_(-)1, ...)")
	}
	specs := strings.Split(indexSpec[1:len(indexSpec)-1], ",")
	var keys []string
	for _, spec := range specs {
		key := parseIndexKey(strings.Trim(spec, " "))  
		if key == "" {
			return nil, errors.New("Compound key sub-key not of format: <key>_(-)1")
		}
		keys = append(keys, key)
	}
	return &mgo.Index{
		Key: keys,
	}, nil
}