Home > Software engineering >  filter query mongoldb Golang
filter query mongoldb Golang

Time:12-07

I am trying to get a list of data that match specific queries but I am getting this error

"(AtlasError) merchant is not allowed or the syntax is incorrect, see the Atlas documentation for more information"

func ...

var result []*model.Package

    ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
    defer cancel()

    tokenData, err := middleware.CtxValue(ctx)

    if err != nil {
        return nil, err
    }

    orQuery := []bson.M{}
    merchant := "abc"
    completedQuery := bson.M{"status": "completed"}
    cancelledQuery := bson.M{"status": "cancelled"}
    orQuery = append(
        orQuery,
        cancelledQuery,
        completedQuery)
    limit64 := int64(limit)
    page64 := int64(page)
    match := bson.M{"$match": bson.M{"$nor": orQuery}}
    var filterQuery primitive.M

    if tokenData.Role == "admin" && merchant != nil {
        filterQuery = bson.M{"merchant": bson.M{"id": merchant}}
    } else {
        filterQuery = bson.M{"user": bson.M{"id": tokenData.Id}}
    }
    paginatedData, err1 := paginate.New(r.Collection).Context(ctx).Limit(limit64).Page(page64).Aggregate(match, filterQuery)
    if err1 != nil {
        return nil, err1
    }


...

CodePudding user response:

filterQuery, which seems to contain { "merchant" : { "id" : "abc" } }, is being passed sepearately to .Aggregate(). But the aggregation framework is expecting to receive something that represents a sequence of pipeline stages. Each of these stages, outlined here in the documentation, are expected to begin with a $ character such as the $match stage.

Currently the database is attempting to process merchant as an options for the pipeline (see here and here). But such an option doesn't exist, hence the error message.

To resolve this, you should incorporate the filterQuery logic into the existing match variable/stage that you are building and passing. Alternatively you can wrap filterQuery in a different $match and then pass both of them (as a single argument) to .Aggregate().

This example in the documentation shows they build multiple stages and then submit them together to .Aggregate() via mongo.Pipeline{...}:

// create the stages
matchStage := bson.D{{"$match", bson.D{{"toppings", "milk foam"}}}}
unsetStage := bson.D{{"$unset", bson.A{"_id", "category"}}}
sortStage := bson.D{{"$sort", bson.D{
    {"price", 1},
    {"toppings", 1}},
}}
limitStage := bson.D{{"$limit", 2}}

// pass the stage into a pipeline
// pass the pipeline as the second paramter in the Aggregate() method
cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage, unsetStage, sortStage, limitStage})
  • Related