// Retrieve retrieves a form gallery from the MongoDB database // collection as well as hydrating the form gallery with form submissions. func Retrieve(context interface{}, db *db.DB, id string) (*Gallery, error) { log.Dev(context, "Retrieve", "Started : Gallery[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "Retrieve", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) var gallery Gallery f := func(c *mgo.Collection) error { log.Dev(context, "Retrieve", "MGO : db.%s.find(%s)", c.Name, mongo.Query(objectID)) return c.FindId(objectID).One(&gallery) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Retrieve", err, "Completed") return nil, err } if err := hydrate(context, db, &gallery); err != nil { log.Error(context, "Retrieve", err, "Completed") return nil, err } log.Dev(context, "Retrieve", "Completed") return &gallery, nil }
func matchAnswers(t *testing.T, ga gallery.Answer, sub submission.Submission, sa submission.Answer) { if ga.SubmissionID.Hex() != sub.ID.Hex() { t.Fatalf("\t%s\tShould match the submission ID : Expected %s, got %s", tests.Failed, sub.ID.Hex(), ga.SubmissionID.Hex()) } t.Logf("\t%s\tShould match the submission ID", tests.Success) if ga.AnswerID != sa.WidgetID { t.Fatalf("\t%s\tShould match the widget ID : Expected %s, got %s", tests.Failed, sa.WidgetID, ga.AnswerID) } t.Logf("\t%s\tShould match the widget ID", tests.Success) if mongo.Query(ga.Answer.Answer) != mongo.Query(sa.Answer) { t.Fatalf("\t%s\tShould match the answer : Expected %s, got %s", tests.Failed, mongo.Query(sa.Answer), mongo.Query(ga.Answer.Answer)) } t.Logf("\t%s\tShould match the answer.", tests.Success) }
// GetByIDs retrieves items by ID from Mongo. func GetByIDs(context interface{}, db *db.DB, ids []string) ([]Item, error) { log.Dev(context, "GetByIDs", "Started : IDs%v", ids) // Get the items from Mongo. var items []Item f := func(c *mgo.Collection) error { q := bson.M{"item_id": bson.M{"$in": ids}} log.Dev(context, "Find", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&items) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByIDs", err, "Completed") return items, err } // If we got an unexpected number of items, throw an error. if len(ids) < len(items) { return nil, fmt.Errorf("Expected %d items, got %d: ", len(ids), len(items)) } log.Dev(context, "GetByIDs", "Completed") return items, nil }
// GetByName retrieves the document for the specified Set. func GetByName(context interface{}, db *db.DB, name string) (*Set, error) { log.Dev(context, "GetByName", "Started : Name[%s]", name) key := "gbn" + name if v, found := cache.Get(key); found { set := v.(Set) log.Dev(context, "GetByName", "Completed : CACHE : Set[%+v]", &set) return &set, nil } var set Set f := func(c *mgo.Collection) error { q := bson.M{"name": name} log.Dev(context, "GetByName", "MGO : db.%s.findOne(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&set) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByName", err, "Completed") return nil, err } // Fix the set so it can be used for processing. set.PrepareForUse() cache.Set(key, set, gc.DefaultExpiration) log.Dev(context, "GetByName", "Completed : Set[%+v]", &set) return &set, nil }
// RetrieveMany retrieves a list of Submission's from the MongoDB database collection. func RetrieveMany(context interface{}, db *db.DB, ids []string) ([]Submission, error) { log.Dev(context, "RetrieveMany", "Started") var objectIDs = make([]bson.ObjectId, len(ids)) for i, id := range ids { if !bson.IsObjectIdHex(id) { log.Error(context, "RetrieveMany", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectIDs[i] = bson.ObjectIdHex(id) } var submissions []Submission f := func(c *mgo.Collection) error { q := bson.M{ "_id": bson.M{ "$in": objectIDs, }, } log.Dev(context, "RetrieveMany", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&submissions) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "RetrieveMany", err, "Completed") return nil, err } log.Dev(context, "RetrieveMany", "Started") return submissions, nil }
// Create adds a new Submission based on a given Form into // the MongoDB database collection. func Create(context interface{}, db *db.DB, formID string, submission *Submission) error { log.Dev(context, "Create", "Started : Form[%s]", formID) if !bson.IsObjectIdHex(formID) { log.Error(context, "Create", ErrInvalidID, "Completed") return ErrInvalidID } if err := submission.Validate(); err != nil { return err } // FIXME: handle Number field maybe with https://docs.mongodb.com/v3.0/tutorial/create-an-auto-incrementing-field/ to resolve race condition count, err := Count(context, db, formID) if err != nil { log.Error(context, "Create", err, "Completed") return err } submission.Number = count + 1 f := func(c *mgo.Collection) error { log.Dev(context, "Create", "MGO : db.%s.insert(%s)", c.Name, mongo.Query(submission)) return c.Insert(submission) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Create", err, "Completed") return err } log.Dev(context, "Create", "Completed") return nil }
// UpdateStatus updates a form submissions status inside the MongoDB database // collection. func UpdateStatus(context interface{}, db *db.DB, id, status string) (*Submission, error) { log.Dev(context, "UpdateStatus", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "UpdateStatus", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) f := func(c *mgo.Collection) error { u := bson.M{ "$set": bson.M{ "status": status, "date_updated": time.Now(), }, } log.Dev(context, "UpdateStatus", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(u)) return c.UpdateId(objectID, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "UpdateStatus", err, "Completed") return nil, err } submission, err := Retrieve(context, db, id) if err != nil { log.Error(context, "UpdateStatus", err, "Completed") return nil, err } log.Dev(context, "UpdateStatus", "Completed") return submission, nil }
// Update updates the form gallery in the MongoDB database // collection. func Update(context interface{}, db *db.DB, id string, gallery *Gallery) error { log.Dev(context, "Update", "Started : Gallery[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "Update", ErrInvalidID, "Completed") return ErrInvalidID } if err := gallery.Validate(); err != nil { log.Error(context, "Update", err, "Completed") return err } objectID := bson.ObjectIdHex(id) gallery.DateUpdated = time.Now() f := func(c *mgo.Collection) error { log.Dev(context, "Update", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(gallery)) return c.UpdateId(objectID, gallery) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Update", err, "Completed") return err } log.Dev(context, "Update", "Completed") return nil }
// Count returns the count of current submissions for a given // form id in the Form Submissions MongoDB database collection. func Count(context interface{}, db *db.DB, formID string) (int, error) { log.Dev(context, "Count", "Completed : Form[%s]", formID) if !bson.IsObjectIdHex(formID) { log.Error(context, "Count", ErrInvalidID, "Completed") return 0, ErrInvalidID } formObjectID := bson.ObjectIdHex(formID) var count int f := func(c *mgo.Collection) error { var err error q := bson.M{ "form_id": formObjectID, } log.Dev(context, "Count", "MGO : db.%s.find(%s).count()", c.Name, mongo.Query(q)) count, err = c.Find(q).Count() return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Count", err, "Completed") return 0, err } log.Dev(context, "Count", "Completed") return count, nil }
// List retrives the form galleries for a given form from the MongoDB database // collection. func List(context interface{}, db *db.DB, formID string) ([]Gallery, error) { log.Dev(context, "List", "Started") if !bson.IsObjectIdHex(formID) { log.Error(context, "List", ErrInvalidID, "Completed") return nil, ErrInvalidID } formObjectID := bson.ObjectIdHex(formID) var galleries = make([]Gallery, 0) f := func(c *mgo.Collection) error { q := bson.M{ "form_id": formObjectID, } log.Dev(context, "List", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&galleries) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "List", err, "Completed") return nil, err } if err := hydrateMany(context, db, galleries); err != nil { log.Error(context, "List", err, "Completed") return nil, err } log.Dev(context, "List", "Completed") return galleries, nil }
// GetByName retrieves the document for the specified query mask. func GetByName(context interface{}, db *db.DB, collection string, field string) (Mask, error) { log.Dev(context, "GetByName", "Started : Collection[%s] Field[%s]", collection, field) key := "gbn" + collection + field if v, found := cache.Get(key); found { mask := v.(Mask) log.Dev(context, "GetByName", "Completed : CACHE : Mask[%+v]", mask) return mask, nil } var mask Mask f := func(c *mgo.Collection) error { q := bson.M{"collection": collection, "field": field} log.Dev(context, "GetByName", "MGO : db.%s.findOne(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&mask) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByName", err, "Completed") return Mask{}, err } cache.Set(key, mask, gc.DefaultExpiration) log.Dev(context, "GetByName", "Completed : Mask[%+v]", mask) return mask, nil }
// RemoveFlag removes a flag from a given Submission in // the MongoDB database collection. func RemoveFlag(context interface{}, db *db.DB, id, flag string) (*Submission, error) { log.Dev(context, "RemoveFlag", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "RemoveFlag", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) f := func(c *mgo.Collection) error { u := bson.M{ "$pull": bson.M{ "flags": flag, }, } log.Dev(context, "RemoveFlag", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(u)) return c.UpdateId(objectID, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "RemoveFlag", err, "Completed") return nil, err } submission, err := Retrieve(context, db, id) if err != nil { log.Error(context, "RemoveFlag", err, "Completed") return nil, err } log.Dev(context, "RemoveFlag", "Completed") return submission, nil }
// Upsert upserts an item to the items collections. func Upsert(context interface{}, db *db.DB, item *Item) error { log.Dev(context, "Upsert", "Started : ID[%s]", item.ID) // If there is no ID, create one. if item.ID == "" { item.ID = uuid.New() } // If CreatedAt is not set, set it. Usually, CreatedAt is joined with the setting of the ID. // In our case, custom ids may be created outside this package for new items. For these // cases we check that a CreatedAt is not yet set. if item.CreatedAt.IsZero() { item.CreatedAt = time.Now() } // Always update UpdatedAt. item.UpdatedAt = time.Now() // Validate the item. if err := item.Validate(); err != nil { log.Error(context, "Upsert", err, "Completed") return err } // Upsert the item. f := func(c *mgo.Collection) error { q := bson.M{"item_id": item.ID} log.Dev(context, "Upsert", "MGO : db.%s.upsert(%s, %s)", c.Name, mongo.Query(q), mongo.Query(item)) _, err := c.Upsert(q, item) return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Upsert", err, "Completed") return err } log.Dev(context, "Upsert", "Completed") return nil }
// RemoveAnswer adds an answer to a form gallery. Duplicated answers // are de-duplicated automatically and will not return an error. func RemoveAnswer(context interface{}, db *db.DB, id, submissionID, answerID string) (*Gallery, error) { log.Dev(context, "RemoveAnswer", "Started : Gallery[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "RemoveAnswer", ErrInvalidID, "Completed") return nil, ErrInvalidID } if !bson.IsObjectIdHex(submissionID) { log.Error(context, "RemoveAnswer", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) answer := Answer{ SubmissionID: bson.ObjectIdHex(submissionID), AnswerID: answerID, } if err := answer.Validate(); err != nil { log.Error(context, "RemoveAnswer", err, "Completed") return nil, err } f := func(c *mgo.Collection) error { u := bson.M{ "$pull": bson.M{ "answers": answer, }, } log.Dev(context, "RemoveAnswer", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(objectID), mongo.Query(u)) return c.UpdateId(objectID, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "RemoveAnswer", err, "Completed") return nil, err } gallery, err := Retrieve(context, db, id) if err != nil { log.Error(context, "RemoveAnswer", err, "Completed") return nil, err } log.Dev(context, "RemoveAnswer", "Completed") return gallery, nil }
// Upsert upserts a pattern to the collection of currently utilized patterns. func Upsert(context interface{}, db *db.DB, pattern *Pattern) error { log.Dev(context, "Upsert", "Started : Type[%s]", pattern.Type) // Validate the pattern. if err := pattern.Validate(); err != nil { log.Error(context, "Upsert", err, "Completed") return err } // Upsert the pattern. f := func(c *mgo.Collection) error { q := bson.M{"type": pattern.Type} log.Dev(context, "Upsert", "MGO : db.%s.upsert(%s, %s)", c.Name, mongo.Query(q), mongo.Query(pattern)) _, err := c.Upsert(q, pattern) return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Upsert", err, "Completed") return err } log.Dev(context, "Upsert", "Completed") return nil }
// Upsert upserts a relationship to the collection of currently utilized relationships. func Upsert(context interface{}, db *db.DB, rel *Relationship) error { log.Dev(context, "Upsert", "Started : Predicate[%s]", rel.Predicate) // Validate the relationship. if err := rel.Validate(); err != nil { log.Error(context, "Upsert", err, "Completed") return err } // Upsert the relationship. f := func(c *mgo.Collection) error { q := bson.M{"predicate": rel.Predicate} log.Dev(context, "Upsert", "MGO : db.%s.upsert(%s, %s)", c.Name, mongo.Query(q), mongo.Query(rel)) _, err := c.Upsert(q, rel) return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Upsert", err, "Completed") return err } log.Dev(context, "Upsert", "Completed") return nil }
// Upsert upserts a view to the collection of currently utilized views. func Upsert(context interface{}, db *db.DB, view *View) error { log.Dev(context, "Upsert", "Started : Name[%s]", view.Name) // Validate the view. if err := view.Validate(); err != nil { log.Error(context, "Upsert", err, "Completed") return err } // Upsert the view. f := func(c *mgo.Collection) error { q := bson.M{"name": view.Name} log.Dev(context, "Upsert", "MGO : db.%s.upsert(%s, %s)", c.Name, mongo.Query(q), mongo.Query(view)) _, err := c.Upsert(q, view) return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Upsert", err, "Completed") return err } log.Dev(context, "Upsert", "Completed") return nil }
// GetLastHistoryByName gets the last written Set within the history. func GetLastHistoryByName(context interface{}, db *db.DB, name string) (*Set, error) { log.Dev(context, "GetLastHistoryByName", "Started : Name[%s]", name) type rslt struct { Name string `bson:"name"` Sets []Set `bson:"sets"` } key := "glhbn" + name if v, found := cache.Get(key); found { result := v.(rslt) log.Dev(context, "GetLastHistoryByName", "Completed : CACHE : Set[%+v]", &result.Sets[0]) return &result.Sets[0], nil } var result rslt f := func(c *mgo.Collection) error { q := bson.M{"name": name} proj := bson.M{"sets": bson.M{"$slice": 1}} log.Dev(context, "GetLastHistoryByName", "MGO : db.%s.find(%s,%s)", c.Name, mongo.Query(q), mongo.Query(proj)) return c.Find(q).Select(proj).One(&result) } if err := db.ExecuteMGO(context, CollectionHistory, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetLastHistoryByName", err, "Complete") return nil, err } if result.Sets == nil { err := errors.New("History not found") log.Error(context, "GetLastHistoryByName", err, "Complete") return nil, err } // Fix the set so it can be used for processing. result.Sets[0].PrepareForUse() cache.Set(key, result, gc.DefaultExpiration) log.Dev(context, "GetLastHistoryByName", "Completed : Set[%+v]", &result.Sets[0]) return &result.Sets[0], nil }
// UpdateAnswer updates the edited answer if it could find it // inside the MongoDB database collection atomically. func UpdateAnswer(context interface{}, db *db.DB, id string, answer AnswerInput) (*Submission, error) { log.Dev(context, "UpdateAnswer", "Started : Submission[%s]", id) if !bson.IsObjectIdHex(id) { log.Error(context, "UpdateAnswer", ErrInvalidID, "Completed") return nil, ErrInvalidID } if err := answer.Validate(); err != nil { log.Error(context, "UpdateAnswer", ErrInvalidID, "Completed") return nil, ErrInvalidID } objectID := bson.ObjectIdHex(id) f := func(c *mgo.Collection) error { q := bson.M{ "_id": objectID, "replies.widget_id": answer.WidgetID, } // Update the nested subdocument using the $ projection operator: // https://docs.mongodb.com/manual/reference/operator/update/positional/ u := bson.M{ "$set": bson.M{ "replies.$.edited": answer.Answer, }, } log.Dev(context, "UpdateAnswer", "MGO : db.%s.update(%s, %s)", c.Name, mongo.Query(q), mongo.Query(u)) return c.Update(q, u) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "UpdateAnswer", err, "Completed") return nil, err } submission, err := Retrieve(context, db, id) if err != nil { log.Error(context, "UpdateAnswer", err, "Completed") return nil, err } log.Dev(context, "UpdateAnswer", "Completed") return submission, nil }
// Delete removes a relationship from from Mongo. func Delete(context interface{}, db *db.DB, predicate string) error { log.Dev(context, "Delete", "Started : Predicate[%s]", predicate) // Remove the relationship. f := func(c *mgo.Collection) error { q := bson.M{"predicate": predicate} log.Dev(context, "Remove", "MGO : db.%s.remove(%s)", c.Name, mongo.Query(q)) return c.Remove(q) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Delete", err, "Completed") return err } log.Dev(context, "Delete", "Completed") return nil }
// Delete removes an item from from Mongo. func Delete(context interface{}, db *db.DB, id string) error { log.Dev(context, "Delete", "Started : ID[%s]", id) // Remove the item. f := func(c *mgo.Collection) error { q := bson.M{"item_id": id} log.Dev(context, "Remove", "MGO : db.%s.remove(%s)", c.Name, mongo.Query(q)) return c.Remove(q) } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Delete", err, "Completed") return err } log.Dev(context, "Delete", "Completed") return nil }
// GetLastHistoryByName gets the last written Regex within the history. func GetLastHistoryByName(context interface{}, db *db.DB, name string) (Regex, error) { log.Dev(context, "GetLastHistoryByName", "Started : Name[%s]", name) type rslt struct { Name string `bson:"name"` Regexs []Regex `bson:"regexs"` } key := "glhbn" + name if v, found := cache.Get(key); found { result := v.(rslt) log.Dev(context, "GetLastHistoryByName", "Completed : CACHE : Regex[%+v]", &result.Regexs[0]) return result.Regexs[0], nil } var result rslt f := func(c *mgo.Collection) error { q := bson.M{"name": name} proj := bson.M{"regexs": bson.M{"$slice": 1}} log.Dev(context, "GetLastHistoryByName", "MGO : db.%s.find(%s,%s)", c.Name, mongo.Query(q), mongo.Query(proj)) return c.Find(q).Select(proj).One(&result) } if err := db.ExecuteMGO(context, CollectionHistory, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetLastHistoryByName", err, "Complete") return Regex{}, err } if result.Regexs == nil { err := errors.New("History not found") log.Error(context, "GetLastHistoryByName", err, "Complete") return Regex{}, err } cache.Set(key, result, gc.DefaultExpiration) log.Dev(context, "GetLastHistoryByName", "Completed : Regex[%+v]", &result.Regexs[0]) return result.Regexs[0], nil }
// GetLastHistoryByName gets the last written query mask within the history. func GetLastHistoryByName(context interface{}, db *db.DB, collection string, field string) (Mask, error) { log.Dev(context, "GetLastHistoryByName", "Started : Collection[%s] Field[%s]", collection, field) type rslt struct { Name string `bson:"name"` Masks []Mask `bson:"masks"` } key := "glhbn" + collection + field if v, found := cache.Get(key); found { result := v.(rslt) log.Dev(context, "GetLastHistoryByName", "Completed : CACHE : Set[%+v]", result.Masks[0]) return result.Masks[0], nil } var result rslt f := func(c *mgo.Collection) error { q := bson.M{"collection": collection, "field": field} proj := bson.M{"masks": bson.M{"$slice": 1}} log.Dev(context, "GetLastHistoryByName", "MGO : db.%s.find(%s,%s)", c.Name, mongo.Query(q), mongo.Query(proj)) return c.Find(q).Select(proj).One(&result) } if err := db.ExecuteMGO(context, CollectionHistory, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetLastHistoryByName", err, "Complete") return Mask{}, err } if result.Masks == nil { err := errors.New("History not found") log.Error(context, "GetLastHistoryByName", err, "Complete") return Mask{}, err } cache.Set(key, result, gc.DefaultExpiration) log.Dev(context, "GetLastHistoryByName", "Completed : Set[%+v]", result.Masks[0]) return result.Masks[0], nil }
// GetNames retrieves a list of query names. func GetNames(context interface{}, db *db.DB) ([]string, error) { log.Dev(context, "GetNames", "Started") var rawNames []struct { Name string } key := "gns" if v, found := cache.Get(key); found { names := v.([]string) log.Dev(context, "GetNames", "Completed : CACHE : Sets[%d]", len(names)) return names, nil } f := func(c *mgo.Collection) error { s := bson.M{"name": 1} log.Dev(context, "GetNames", "MGO : db.%s.find({}, %s).sort([\"name\"])", c.Name, mongo.Query(s)) return c.Find(nil).Select(s).Sort("name").All(&rawNames) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetNames", err, "Completed") return nil, err } if rawNames == nil { log.Error(context, "GetNames", ErrNotFound, "Completed") return nil, ErrNotFound } names := make([]string, len(rawNames)) for i := range rawNames { names[i] = rawNames[i].Name } cache.Set(key, names, gc.DefaultExpiration) log.Dev(context, "GetNames", "Completed : Sets[%d]", len(names)) return names, nil }
// Upsert upserts the provided form into the MongoDB database collection. func Upsert(context interface{}, db *db.DB, form *Form) error { log.Dev(context, "Upsert", "Started") var isNewForm bool // If there is no ID probided, we should set one as this is an Upsert // operation. It is also important to remember if this was a new form or not // because we need to update the stats if this wasn't a new form. if form.ID.Hex() == "" { form.ID = bson.NewObjectId() isNewForm = true form.DateCreated = time.Now() } form.DateUpdated = time.Now() if err := form.Validate(); err != nil { log.Error(context, "Upsert", err, "Completed") return err } f := func(c *mgo.Collection) error { log.Dev(context, "Upsert", "MGO : db.%s.upsert(%s, %s)", c.Name, mongo.Query(form.ID.Hex()), mongo.Query(form)) _, err := c.UpsertId(form.ID, form) return err } if err := db.ExecuteMGO(context, Collection, f); err != nil { log.Error(context, "Upsert", err, "Completed") return err } // New forms don't have any stats so don't bother updating it. if !isNewForm { if _, err := UpdateStats(context, db, form.ID.Hex()); err != nil { log.Error(context, "Upsert", err, "Completed") return err } } log.Dev(context, "Upsert", "Completed") return nil }
// EnsureIndexes perform index create commands against Mongo for the indexes // specied in each query for the set. It will attempt to ensure all indexes // regardless if one fails. Then reports all failures. func EnsureIndexes(context interface{}, db *db.DB, set *Set) error { log.Dev(context, "EnsureIndexes", "Started : Name[%s]", set.Name) var errStr string for _, q := range set.Queries { if len(q.Indexes) == 0 { continue } f := func(c *mgo.Collection) error { for _, idx := range q.Indexes { mgoIdx := mgo.Index{ Key: idx.Key, Unique: idx.Unique, DropDups: idx.DropDups, Background: idx.Background, Sparse: idx.Sparse, } log.Dev(context, "EnsureIndexes", "MGO : db.%s.ensureindex(%s)", c.Name, mongo.Query(mgoIdx)) if err := c.EnsureIndex(mgoIdx); err != nil { log.Error(context, "EnsureIndexes", err, "Ensuring Index") errStr += fmt.Sprintf("[%s:%s] ", strings.Join(idx.Key, ","), err.Error()) } } return nil } if err := db.ExecuteMGO(context, q.Collection, f); err != nil { log.Error(context, "EnsureIndexes", err, "Completed") return err } } if errStr != "" { return errors.New(errStr) } log.Dev(context, "EnsureIndexes", "Completed") return nil }
// GetByCollection retrieves the masks for the specified collection. func GetByCollection(context interface{}, db *db.DB, collection string) (map[string]Mask, error) { log.Dev(context, "GetByCollection", "Started : Collection[%s]", collection) key := "gbc" + collection if v, found := cache.Get(key); found { mskMap := v.(map[string]Mask) log.Dev(context, "GetByCollection", "Completed : CACHE : Masks[%d]", len(mskMap)) return mskMap, nil } var masks []Mask f := func(c *mgo.Collection) error { q := bson.M{"$or": []bson.M{bson.M{"collection": collection}, bson.M{"collection": "*"}}} log.Dev(context, "GetByCollection", "MGO : db.%s.findOne(%s)", c.Name, mongo.Query(q)) return c.Find(q).All(&masks) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByCollection", err, "Completed") return nil, err } if masks == nil { log.Error(context, "GetByCollection", ErrNotFound, "Completed") return nil, ErrNotFound } mskMap := make(map[string]Mask, len(masks)) for _, msk := range masks { mskMap[msk.Field] = msk } cache.Set(key, mskMap, gc.DefaultExpiration) log.Dev(context, "GetByCollection", "Completed : Masks[%d]", len(mskMap)) return mskMap, nil }
// GetByPredicate retrieves a relationship by predicate from Mongo. func GetByPredicate(context interface{}, db *db.DB, predicate string) (*Relationship, error) { log.Dev(context, "GetByPredicate", "Started : Predicate[%s]", predicate) // Get the relationship from Mongo. var rel Relationship f := func(c *mgo.Collection) error { q := bson.M{"predicate": predicate} log.Dev(context, "Find", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&rel) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByPredicate", err, "Completed") return &rel, err } log.Dev(context, "GetByPredicate", "Completed") return &rel, nil }
// GetByType retrieves a pattern by type from Mongo. func GetByType(context interface{}, db *db.DB, itemType string) (*Pattern, error) { log.Dev(context, "GetByType", "Started : Type[%s]", itemType) // Get the pattern from Mongo. var pattern Pattern f := func(c *mgo.Collection) error { q := bson.M{"type": itemType} log.Dev(context, "Find", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&pattern) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByType", err, "Completed") return &pattern, err } log.Dev(context, "GetByType", "Completed") return &pattern, nil }
// GetByID retrieves a single item by ID from Mongo. func GetByID(context interface{}, db *db.DB, id string) (Item, error) { log.Dev(context, "GetByID", "Started : ID[%s]", id) // Get the items from Mongo. var itm Item f := func(c *mgo.Collection) error { q := bson.M{"item_id": id} log.Dev(context, "GetByID", "MGO : db.%s.find(%s)", c.Name, mongo.Query(q)) return c.Find(q).One(&itm) } if err := db.ExecuteMGO(context, Collection, f); err != nil { if err == mgo.ErrNotFound { err = ErrNotFound } log.Error(context, "GetByID", err, "Completed") return itm, err } log.Dev(context, "GetByID", "Completed") return itm, nil }