Search code examples
mongodbgobson

How to write bson form of mongo query in golang?


I can query my mongodb collection to get the ipv4Addresses based on the nfType and the minimum distance using the command line query

db.nfinstancesdb.aggregate([
  {
    "$match": {
      "nfType": "AMF"
    }
  },
  {
    "$unwind": "$ipv4Addresses"
  },
  {
    $group: {
      "_id": "$distance",
      "ipv4Addresses": {
        "$addToSet": "$ipv4Addresses"
      }
    }
  },
  {
    "$sort": {
      "_id": 1
    }
  },
  {
    "$limit": 1
  }
])

This give the output am expecting as

[{"_id": 10,"ipv4Addresses": ["172.16.0.11","172.16.0.10"]}]

How can I write the bson form of the above query on Go?

I did in the function below but am getting all the ipv4Addresses instead of the above result.

func (m *NfInstanceDataAccess) FindIp(nfType string) ([]NfInstance, error) {
    var ip []NfInstance

    collection := db.C(COLLECTION)
    pipeline := mongo.Pipeline{
        {{"$match", bson.D{
            {"nfType", "AMF"},
        }}},
        {{"$unwind", "$ipv4Addresses"}},
        {{"$group", bson.D{
            {"_id", "$distance"},
            {"ipv4Addresses", bson.D{
                {"$addToSet", "$ipv4Addresses"},
            }},
        }}},
        {{"$sort", bson.D{
            {"_id", 1},
        }}},
        {{"$limit", 1}},
    }

    cursor, err := collection.Aggregate(context.Background(), pipeline)
    defer cursor.Close(context.Background())
    for cursor.Next(context.Background()) {
        var ip []NfInstance
        err := cursor.Decode(&ip)
        if err != nil {
            log.Fatal(err)
        }
        //fmt.Println(doc)
    }
    return ip, nil
}


My collection has the following items

{
    "nfInstanceID": "1",
    "nfType": [
      "AMF"
    ],
    "nfStatus": [
      "REGISTERED"
    ],
    "ipv4Addresses": [
      "172.16.0.10"
    ],
    "distance": 10
  },
  {
    "nfInstanceID": "2",
    "nfType": [
      "UPF"
    ],
    "nfStatus": [
      "REGISTERED"
    ],
    "ipv4Addresses": [
      "172.16.0.20"
    ],
    "distance": 20
  },
  {
    "nfInstanceID": "3",
    "nfType": [
      "AMF"
    ],
    "nfStatus": [
      "REGISTERED"
    ],
    "ipv4Addresses": [
      "172.16.0.30"
    ],
    "distance": 30
  },
  {
    "nfInstanceID": "4",
    "nfType": [
      "AMF"
    ],
    "nfStatus": [
      "REGISTERED"
    ],
    "ipv4Addresses": [
      "172.16.0.11"
    ],
    "distance": 10
  }

And I am expecting the same or similar output.


Solution

  • The problem with your golang code is you didn't group.

    You can make use of Pipe which prepares a pipeline to aggregate:

    pipe := db.C(COLLECTION).Pipe([]bson.M{
        {"$match":  bson.M{"nfType": "AMF"}},
        {"$unwind": "$ipv4Addresses"},
        {"$group":  bson.M{
                           "_id": "$distance",
                           "ipv4Addresses": bson.M{"$addToSet": "$ipv4Addresses"},
                          }},
        {"$sort": bson.M{"_id": 1}},
        {"$limit": 1},
    
    })
    
    err := pipe.All(&ip)