skip to Main Content

Trying to use mongo-go-driver SetLet in the aggregate options to pass user variables defined earlier in my function into my aggregation pipeline.

Trying to parse the documentation for this…

SetLet asks for just an interface{} for the input parameter.

I’m using a correctly formatted pipeline aggregation using “$$variableName” where I’m hoping the SetLet will fill in.

I’ve tried passing in a bson.M and a map[string]interface{} but neither of these result in a successful pass through for me (aggregation returns no documents).

Has anyone successfully used SetLet in mongo-go-driver and has a working example of how to use it properly?

Basic code example:

package test

import (
    "context"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func test() {
    // I would connect to an actual mongo database and get an actual collection, but I won't for example
    var col mongo.Collection

    // the variable I want to set via "Let" in my pipeline
    externalId := "test"
    let := bson.M{"externalId": externalId}
    options := options.Aggregate().SetLet(let)

    // The pipeline aggregation, I want my external variable to take place of "$$externalId"
    aggregation := bson.A{bson.D{{"$match", bson.D{{"id", "$$externalId"}}}}}

    // Perform aggregation and store result (Result will be empty because no documents were returned, because $match did not work)
    cursor, _ := col.Aggregate(context.TODO(), aggregation, options)
    var result any
    cursor.All(context.TODO(), &result)
}

2

Answers


  1. Chosen as BEST ANSWER

    Figured it out. My usage of SetLet was correct. The problem was that it seems like I cannot use a user defined variable directly in my $match pipeline stage. I need to use $expr in order to properly use my user var.

    bson.D{
                {"$match",
                    bson.D{
                        {"$expr",
                            bson.D{
                                {"$eq",
                                    bson.A{
                                        "$id",
                                        "$$externalId",
                                    },
                                },
                            },
                        },
                    },
                },
            }
    

  2. @Tyler’s answer is correct about the using of $expr operator. Here is the note from the official documentation for the let option:

    To filter results using a variable in a pipeline $match stage, you must access the variable within the $expr operator.

    See Use Variables in let.

    The use of bson.D results in ugly code. It’s better to use bson.M:

    aggregation := bson.A{
        bson.M{
            "$match": bson.M{
                "$expr": bson.M{
                    "$eq": bson.A{"$id", "$$externalId"},
                },
            },
        },
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search