es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Filtro de Mongo funciona dentro de la terminal de Mongo, pero no funciona cuando se escribe en Go.

Mongo: 4.4
Go: 1.17.3

Estoy intentando obtener documentos con valores de campo de cadena más largos que cuatro símbolos.
Aquí está la consulta que uso dentro de la consola de mongo:

db.player.find({
    "name": { "$exists": true },
    "$expr": { "$gt": [ { "$strLenCP": "$name" }, 4 ] } 
})

Y aquí está la misma consulta pero codificada como filtro “bson” en “go”:

longName := bson.M{
    "name": bson.M{"$exists": true},
    "$expr": bson.M{
        "$gt": bson.A{
            bson.M{"$strLenCP": "$name"},
            4,
        },
    },
}
fmc, err := collection.Find(context.TODO(), longName)
if err != nil {
    log.Panic(err)
}
var longBoi models.Player
err = fmc.Decode(&longBoi)
if err != nil {
    log.Panic(err) 
    // pánico aquí:
    // 2021/12/15 15:53:46 EOF
    // panic: EOF
}

La primera consulta devolverá los documentos deseados con valores de campo de cadena de longitud mayor a un número específico. La segunda consulta dará un error con el mensaje “EOF”, un sello de tiempo y una pila de llamadas. El depurador indica que el lote “batch” dentro del cursor “fmc” no contiene datos.

¿Qué está mal en el segundo caso?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema en el segundo caso es que el método Decode solo puede decodificar un único documento de la colección de resultados. Cuando se utiliza el método Find en el controlador de MongoDB para Go, la colección de resultados se retorna como un cursor que debe ser iterado para recuperar todos los documentos que coinciden con la consulta. En otras palabras, el método Decode debe ser llamado múltiples veces hasta alcanzar el final de la colección de resultados.

    Para solucionar el problema, el código debe utilizar un ciclo para iterar sobre el cursor y decodificar todos los documentos. Aquí tienes un ejemplo:

    fmc, err := collection.Find(context.TODO(), longName)
    if err != nil {
        log.Panic(err)
    }
    
    var longBois []models.Player
    for fmc.Next(context.TODO()) {
        var longBoi models.Player
        err = fmc.Decode(&longBoi)
        if err != nil {
            log.Panic(err)
        }
        longBois = append(longBois, longBoi)
    }
    
    if err := fmc.Err(); err != nil {
        log.Panic(err)
    }
    

    Este código iterará sobre el cursor utilizando el método Next, decodificará cada documento utilizando el método Decode y lo agregará a una slice de models.Player. Finalmente, el código verifica si ocurrieron errores durante la iteración utilizando el método Err.

    Ten en cuenta que el método Find retorna un cursor que debe ser cerrado explícitamente después de la iteración utilizando el método Close.

Comments are closed.