我有下面的结构。我使用 Golang 1.9.2 。
// EventBoost describes the model of a EventBoost type EventBoost struct { ID string `bson:"_id" json:"_id" valid:"alphanum,printableascii"` CampaignID string `bson:"_campaign_id" json:"_campaign_id" valid:"alphanum,printableascii"` Name string `bson:"name" json:"name"` Description string `bson:"description" json:"description"` Level string `bson:"level" json:"level"` EventID string `bson:"_event_id" json:"_event_id" valid:"alphanum,printableascii"` StartDate time.Time `bson:"start_date" json:"start_date"` EndDate time.Time `bson:"end_date" json:"end_date"` IsPublished bool `bson:"is_published" json:"is_published"` CreatedBy string `bson:"created_by" json:"created_by"` CreatedAt time.Time `bson:"created_at" json:"created_at"` ModifiedAt time.Time `bson:"modified_at" json:"modified_at"` } // LocationBoost describes the model of a LocationBoost type LocationBoost struct { ID string `bson:"_id" json:"_id" valid:"alphanum,printableascii"` CampaignID string `bson:"_campaign_id" json:"_campaign_id" valid:"alphanum,printableascii"` Name string `bson:"name" json:"name"` Description string `bson:"description" json:"description"` Level string `bson:"level" json:"level"` LocationID string `bson:"_location_id" json:"_location_id" valid:"alphanum,printableascii"` StartDate time.Time `bson:"start_date" json:"start_date"` EndDate time.Time `bson:"end_date" json:"end_date"` IsPublished bool `bson:"is_published" json:"is_published"` CreatedBy string `bson:"created_by" json:"created_by"` CreatedAt time.Time `bson:"created_at" json:"created_at"` ModifiedAt time.Time `bson:"modified_at" json:"modified_at"` } // Campaign describes the model of a Campaign type Campaign struct { ID string `bson:"_id" json:"_id" valid:"alphanum,printableascii"` Name string `bson:"name" json:"name"` Description string `bson:"description" json:"description"` EventBoostIDs []string `bson:"event_boost_ids" json:"event_boost_ids"` LocationBoostIDs []string `bson:"location_boost_ids" json:"location_boost_ids"` StartDate time.Time `bson:"start_date" json:"start_date"` EndDate time.Time `bson:"end_date" json:"end_date"` IsPublished bool `bson:"is_published" json:"is_published"` CreatedBy string `bson:"created_by" json:"created_by"` CreatedAt time.Time `bson:"created_at" json:"created_at"` ModifiedAt time.Time `bson:"modified_at" json:"modified_at"` }
一个 活动 (了解营销活动)是由 事件 或 地点 可以与(基本或溢价)的水平而提高。广告活动有开始日期和结束日期,推广活动也是如此。
函数GetEventLevel必须返回给定事件的级别。
GetEventLevel
// GetEventLevel of an event func (dao *campaignDAO) GetEventLevel(eventID string) (string, error) { }
如果事件在 有效的广告系列中 被增强(isPublishedis true),并且 增强被激活 (isPublishedis true)并且 现在日期在boost的开始日期和结束日期之间 ,则我的Event被 增强 ,因此该函数返回级别(基本或高级)。否则,它返回"standard"。
isPublished
true
"standard"
我的问题是: 我可以完全通过Mongo做到这一点吗? 还是我需要使用Golang在DAO中执行一些逻辑?
如果我希望Mongo能够做到这一点,我不知道该怎么做。据我了解,我首先需要查找事件和活动的位置,然后在其中搜索日期,但是。
这样做 最 (和最困难的部分),你想要可以很容易地在MongoDB中做什么。返回“基本”,“高级”或“标准”的最后一步很可能也可以完成,但是我认为这不值得麻烦,因为在Go中这很琐碎。
在MongoDB中,请使用Aggregation框架。可mgo通过Collection.Pipe()方法在包装中找到。您必须向其传递一个切片,每个元素对应一个聚合阶段。
mgo
Collection.Pipe()
回到您的示例。您的GetEventLevel()方法可以这样实现:
GetEventLevel()
func (dao *campaignDAO) GetEventLevel(eventID string) (string, error) { c := sess.DB("").C("eventboosts") // sess represents a MongoDB Session now := time.Now() pipe := c.Pipe([]bson.M{ { "$match": bson.M{ "_event_id": eventID, // Boost for the specific event "is_published": true, // Boost is active "start_date": bson.M{"$lt": now}, // now is between start and end "end_date": bson.M{"$gt": now}, // now is between start and end }, }, { "$lookup": bson.M{ "from": "campaigns", "localField": "_campaign_id", "foreignField": "_id", "as": "campaign", }, }, {"$unwind": "$campaign"}, { "$match": bson.M{ "campaign.is_published": true, // Attached campaign is active }, }, }) var result []*EventBoost if err := pipe.All(&result); err != nil { return "", err } if len(result) == 0 { return "standard", nil } return result[0].Level, nil }
如果您最多只需要一个EventBoost(或者可能不会同时有更多),请使用$limitstage将结果限制为一个,然后$project仅用于获取level字段,仅此而已。
EventBoost
$limit
$project
level
使用此管道进行上述简化/优化:
pipe := c.Pipe([]bson.M{ { "$match": bson.M{ "_event_id": eventID, // Boost for the specific event "is_published": true, // Boost is active "start_date": bson.M{"$lt": now}, // now is between start and end "end_date": bson.M{"$gt": now}, // now is between start and end }, }, { "$lookup": bson.M{ "from": "campaigns", "localField": "_campaign_id", "foreignField": "_id", "as": "campaign", }, }, {"$unwind": "$campaign"}, { "$match": bson.M{ "campaign.is_published": true, // Attached campaign is active }, }, {"$limit": 1}, // Fetch at most 1 result { "$project": bson.M{ "_id": 0, // We don't even need the EventBoost's ID "level": "$level", // We do need the level and nothing more }, }, })