Search code examples
mongodbgoaggregation-frameworkmongo-go

Multiple top level aggregate queries in a MongoDB Pipeline


I have the following query:

match := bson.D{{"$match", bson.D{{"venue", venueID}}}}
group := bson.D{{"$lookup", bson.M{
    "from":         "labels",
    "localField":   "label_ids",
    "foreignField": "_id",
    "as":           "labels",
}}, {"$graphLookup", bson.M{
    "from":             "menus",
    "startWith":        "$child_ids",
    "connectFromField": "child_ids",
    "connectToField":   "_id",
    "as":               "children",
    "maxDepth":         5,
    "depthField":       "level",
}}}

cur, err := m.collection.Aggregate(ctx, mongo.Pipeline{group, match})

I have two fields that are relational, one of them is a graph structure (menus), each parent element has an array of IDs for each child element.

The second field, labels, is just a one to many sort of query. Labels and menus are supposed to be re-usable, so not embedded in a single parent entity. The query outlined above makes sense to me, however I get the following error:

A pipeline stage specification object must contain exactly one field.

Thanks!


Solution

  • Each element in a MongoDB pipeline must be a single stage, e.g. $match, $group etc.

    Your group element contains 2 stages: $lookup and $graphLookup.

    Split them and list them individually:

    match := bson.D{{"$match", bson.D{{"venue", venueID}}}}
    group := bson.D{{"$lookup", bson.M{
        "from":         "labels",
        "localField":   "label_ids",
        "foreignField": "_id",
        "as":           "labels",
    }}}
    graphLookup := bson.D{{"$graphLookup", bson.M{
        "from":             "menus",
        "startWith":        "$child_ids",
        "connectFromField": "child_ids",
        "connectToField":   "_id",
        "as":               "children",
        "maxDepth":         5,
        "depthField":       "level",
    }}}
    
    cur, err := m.collection.Aggregate(ctx, mongo.Pipeline{group, graphLookup, match})