MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Obtenir une valeur dans une référence d'une recherche avec MongoDB et Golang

Faire le plus (et la partie la plus difficile) de ce que vous voulez peut facilement être fait dans MongoDB. La dernière étape lors du retour de "basique", "premium" ou "standard" peut également être effectuée, mais je pense que cela ne vaut pas la peine car c'est trivial dans Go.

Dans MongoDB, utilisez le framework d'agrégation pour ça. Ceci est disponible dans le mgo package via Collection.Pipe() méthode. Il faut lui passer une tranche, chaque élément correspond à une étape d'agrégation. Lisez cette réponse pour plus de détails :Comment obtenir un agrégat à partir d'une collection MongoDB

Revenons à votre exemple. Votre GetEventLevel() méthode pourrait être implémentée comme ceci :

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
}

Si vous n'avez besoin que d'au plus un EventBoost (ou il peut ne pas y en avoir plus en même temps), utilisez $limit étape pour limiter les résultats à un seul, et utilisez $project pour récupérer uniquement le level champ et rien de plus.

Utilisez ce pipeline pour la simplification/optimisation mentionnée ci-dessus :

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