How to write bson form of mongo query in golang?

我与影子孤独终老i 提交于 2020-03-24 03:32:40

问题


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.


回答1:


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)



回答2:


If you are using the official MongoDB Go driver you can utilise Collection.Aggregate to perform Aggregation Pipeline. The example Go code snippet that you posted is using find() which is different than aggregation.

For example, using MongoDB Go driver v1.0.4 (current):

collection := client.Database("dbname").Collection("collname")
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()) {
    doc := bson.D{}
    err := cursor.Decode(&doc)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(doc)
}

The example documents that you posted only have 1 element for all of ipv4Addresses, I'm assuming that this is just an example. If however, all of the documents do only have 1 element array for ipv4Addresses you're likely better off to just use $project.

Generally bson.D is used when serialising to BSON (and when order matters).



来源:https://stackoverflow.com/questions/56948324/how-to-write-bson-form-of-mongo-query-in-golang

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!