func ModifyChannels(db *mgo.Database) (err error) { Topics := db.C(topicsCollection) notNull := bson.M{"$ne": ""} query := bson.M{ "user": notNull, "org": notNull, } var topics []Topic // Modify user setting err = Topics.Find(query).All(&topics) handle_errors(err) for _, topic := range topics { channels := make([]models.Channel, 0) for _, name := range topic.Channels { channel := new(models.Channel) channel.Name = name channel.Enabled = true channels = append(channels, *channel) } Topics.Update(bson.M{"_id": topic.Id}, bson.M{ "$set": bson.M{ "channels": channels, }, }) } // fmt.Println("Updated", change.Updated, "documents in `", topicsCollection, "` collection") // Modify org setting query["user"] = "" change, err := Topics.UpdateAll( query, bson.M{ "$set": map[string][]models.Channel{ "channels": make([]models.Channel, 0), }, }, ) handle_errors(err) fmt.Println("Updated", change.Updated, "documents in `", topicsCollection, "` collection") return }
// InsertOrUpdateTopic adds a topic in `topics` collection if it doesn't exist // Or it update the topic if it exists // // This is not a very effecient way of doing it but we are doing it at the cost // of the data structure we want. // // One of the limitations is that mongo is not yet capable of upserting to array // of documents. For this to happen in a simple way the data structure has to // change from channels: []Channel to channels: map[string]interface func InsertOrUpdateTopic(org, ident, channelName, attr string, val bool, user string) error { var channels []db.Channel var channel db.Channel var doc utils.M var spec utils.M found := new(db.Topic) query := utils.M{ "org": org, "user": user, // empty for org "ident": ident, } // See if this setting already exists err := db.Conn.GetOne( db.TopicCollection, query, found, ) // Fetch the global setting // Because if the above setting already doesn't exist, then set the other // attr to what is set in global global := new(db.Topic) q := utils.M{"org": "", "user": "", "ident": ident} e := db.Conn.GetOne(db.TopicCollection, q, &global) if e == nil { for _, ch := range global.Channels { if ch.Name == channelName { if attr == "Default" { channel.Locked = ch.Locked } else if attr == "Locked" { channel.Default = ch.Default } } else if err != nil { channels = append(channels, ch) } } } channel.Name = channelName if attr == "Default" { channel.Default = val } else if attr == "Locked" { channel.Locked = val } else { channel.Enabled = val } channels = append(channels, channel) // If it doesn't exist, insert and return if err != nil { topic := new(db.Topic) topic.PrepareSave() topic.Ident = ident topic.Organization = org topic.User = user topic.Channels = channels Insert(topic) return nil } // If it does exist, find the document in the array and modify it // Do one of the two depending on whether its present or not // Step 1. if its not present, add to channels array // Step 2. if its present, set the value query["channels.name"] = channelName err = db.Conn.GetOne( db.TopicCollection, query, found, ) // Step 1. Add to set and return if err != nil { doc = utils.M{ "$addToSet": utils.M{ "channels": channel, }, } delete(query, "channels.name") return updateTopics(query, doc) } // Step 2. Else set the value if attr == "Default" { spec = utils.M{ "channels.$.default": val, } } else if attr == "Locked" { spec = utils.M{ "channels.$.locked": val, } } else if attr == "Enabled" { spec = utils.M{ "channels.$.enabled": val, } } doc = utils.M{ "$set": spec, } return updateTopics(query, doc) }