// 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) }