如何在Golang中编写bson形式的mongo查询?

时间:2019-07-09 08:25:38

标签: mongodb go bson

我可以使用命令行查询查询mongodb集合以基于nfType和最小距离获取ipv4Addresses

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

这使输出预期为

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

如何在Go上编写上述查询的bson形式?

我在下面的函数中做过,但是正在获取所有ipv4Addresses 而不是上面的结果。

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
}


我的收藏有以下物品

{
    "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
  }

我期望输出相同或相似。

2 个答案:

答案 0 :(得分:0)

您的golang代码存在问题是您没有分组。

您可以利用Pipe来准备要汇总的管道:

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)

答案 1 :(得分:0)

如果您使用的是官方MongoDB Go driver,则可以利用Collection.Aggregate来执行Aggregation Pipeline。您发布的示例Go代码段使用的是find(),与聚合不同。

例如,使用MongoDB Go驱动程序v1.0.4(当前):

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)
}

您发布的示例文档对于ipv4Addresses的全部仅包含1个元素,我假设这只是一个示例。但是,如果所有文档的ipv4Addresses都只有1个元素数组,那么最好只使用$project

序列化为BSON时(以及顺序很重要时)通常使用bson.D