这样做 最
(和最困难的部分),你想要可以很容易地在MongoDB中做什么。返回“基本”,“高级”或“标准”的最后一步很可能也可以完成,但是我认为这不值得麻烦,因为在Go中这很琐碎。
在MongoDB中,请使用Aggregation框架。可
mgo通过
Collection.Pipe()方法在包装中找到。您必须向其传递一个切片,每个元素对应一个聚合阶段。
回到您的示例。您的
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字段,仅此而已。
使用此管道进行上述简化/优化:
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 }, },})


