MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Rufen Sie einen Wert in einer Referenz einer Suche mit MongoDB und Golang ab

am meisten tun (und der schwierigste Teil) dessen, was Sie wollen, können Sie ganz einfach in MongoDB erledigen. Der letzte Schritt bei der Rückgabe von "Basic", "Premium" oder "Standard" kann höchstwahrscheinlich ebenfalls durchgeführt werden, aber ich denke, es lohnt sich nicht, da dies in Go trivial ist.

Verwenden Sie in MongoDB das Aggregation Framework dafür. Dies ist im mgo verfügbar Paket über Collection.Pipe() Methode. Sie müssen ihm einen Slice übergeben, jedes Element entspricht einer Aggregationsstufe. Lesen Sie diese Antwort für weitere Details:So erhalten Sie ein Aggregat aus einer MongoDB-Sammlung

Zurück zu deinem Beispiel. Ihr GetEventLevel() Methode könnte wie folgt implementiert werden:

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
}

Wenn Sie höchstens einen EventBoost benötigen (oder es dürfen nicht mehr gleichzeitig sein), verwenden Sie $limit Stage, um die Ergebnisse auf ein einziges zu beschränken, und verwenden Sie $project um nur das level abzurufen Feld und nichts weiter.

Verwenden Sie diese Pipeline für die oben genannte Vereinfachung/Optimierung:

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