Как написать bson форму запроса монго в Голанге? - PullRequest
1 голос
/ 09 июля 2019

Я могу запросить мою коллекцию mongodb, чтобы получить ipv4Addresses на основе nfType и минимального расстояния, используя запрос командной строки

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

Как я могу написать форму bson вышеупомянутого запроса на Go?

Я выполнил следующую функцию, но получаю все адреса ipv4 вместо приведенного выше результата.

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 голосов
/ 10 июля 2019

Если вы используете официальный MongoDB Go драйвер , вы можете использовать Collection.Aggregate для выполнения Агрегационный конвейер . В приведенном вами фрагменте кода 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)
}

Примеры документов, которые вы опубликовали, имеют только 1 элемент для всех ipv4Addresses, я предполагаю, что это только пример. Однако, если все документы имеют только 1 элемент массива для ipv4Addresses, вам, вероятно, лучше просто использовать $ project .

Обычно bson.D используется при сериализации в BSON (и когда заказ имеет значение).

0 голосов
/ 09 июля 2019

Проблема с вашим кодом 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)
...