sql >> Base de Datos >  >> NoSQL >> MongoDB

Obtenga un valor en una referencia de una búsqueda con MongoDB y Golang

Hacer la mayoría (y la parte más difícil) de lo que desea se puede hacer fácilmente en MongoDB. El paso final al devolver "básico", "premium" o "estándar" probablemente también se pueda hacer, pero creo que no vale la pena, ya que es trivial en Go.

En MongoDB, use el Marco de agregación para esto. Esto está disponible en el mgo paquete a través de Collection.Pipe() método. Tienes que pasarle un segmento, cada elemento corresponde a una etapa de agregación. Lea esta respuesta para obtener más detalles:Cómo obtener un agregado de una colección de MongoDB

Volvamos a tu ejemplo. Tu GetEventLevel() El método podría implementarse así:

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 solo necesita como máximo un EventBoost (o puede que no haya más al mismo tiempo), use $limit etapa para limitar los resultados a uno solo, y use $project para obtener solo el level campo y nada más.

Utilice esta canalización para la simplificación/optimización mencionada anteriormente:

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