使用MongoDB和Golang在查询参考中获取值 [英] Get a value in a reference of a lookup with MongoDB and Golang

查看:30
本文介绍了使用MongoDB和Golang在查询参考中获取值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下结构.我使用的是 Golang 1.9.2 .

I have the structures below. I use 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"`
}

广告系列(理解营销活动)由事件位置组成,可以提高一级(基本或高级) .广告系列有开始日期和结束日期,因此促销活动也有.

A Campaign (understand a marketing campaign) is made of Events or Locations that can be boosted with a level (basic or premium). A campaign has a start and a end date, so do have the boosts.

函数GetEventLevel必须向我返回给定事件的级别.

The function GetEventLevel has to return me the level of a given event.

// GetEventLevel of an event
func (dao *campaignDAO) GetEventLevel(eventID string) (string, error) {
}

如果事件是在有效的广告系列(isPublishedtrue)中增强的,并且该增强是活动的(isPublishedtrue)并且现在日期介于增强的开始日期和结束日期之间,则我的事件被增强,因此该函数返回级别(基本或高级).否则,它返回"standard".

If the event is boosted in an active campaign (isPublished is true), and the boost is active (isPublished is true) and the now date is between the start and end date of the boost, then my Event is boosted, so the function returns the level (basic or premium). Else, it returns "standard".

我的问题是:我可以对Mongo完全做到这一点吗?还是我需要使用Golang在DAO中执行一些逻辑?

如果我可以用Mongo做到这一点,我希望,我不知道如何做到这一点.据我了解,我首先需要查找事件和活动的位置,然后在其中搜索日期,但是..

If I can do this with Mongo, what I hope, I have no idea how to do this. From what I understand, I would first need to lookup the events and the locations of the campaign, and then search in it with dates, but..

推荐答案

在MongoDB中轻松完成所需的 (也是最难的部分).返回基本",高级"或标准"的最后一步很可能也可以完成,但是我认为这不值得麻烦,因为在Go中这很琐碎.

Doing most (and the hardest part) of what you want can easily be done in MongoDB. The final step when returning "basic", "premium" or "standard" most likely can also be done, but I think it's not worth the hassle as that is trivial in Go.

在MongoDB中,为此使用聚合框架.可通过 Collection.Pipe() mgo包中找到该文件.方法.您必须向其传递一个切片,每个元素都对应一个聚合阶段.阅读此答案以获取更多详细信息:如何获取MongoDB集合中的聚合

In MongoDB use the Aggregation framework for this. This is available in the mgo package via the Collection.Pipe() method. You have to pass a slice to it, each element corresponds to an aggregation stage. Read this answer for more details: How to Get an Aggregate from a MongoDB Collection

回到您的示例.您的GetEventLevel()方法可以这样实现:

Back to your example. Your GetEventLevel() method could be implemented like this:

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(或者可能没有同时出现更多),请使用$limit阶段将结果限制为一个,然后使用$project仅获取字段,仅此而已.

If you only need at most one EventBoost (or there may not be more at the same time), use $limit stage to limit results to a single one, and use $project to only fetch the level field and nothing more.

使用此管道进行上述简化/优化:

Use this pipeline for the above mentioned simplification / optimization:

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

这篇关于使用MongoDB和Golang在查询参考中获取值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆