web-dev-qa-db-fra.com

Mongo-go-driver obtient l'ID d'objet du résultat d'insertion

Après avoir utilisé InsertOne pour créer un nouveau document, lorsque je renvoie le résultat, j'obtiens un tableau de nombres plutôt qu'un ObjectID. Dans la base de données, l'ID génère correctement.

type User struct {
  ID       string
  Email    string
  Username string
  Password string
}

var db = ...

// UserStore creates user
func UserStore(c echo.Context) (err error) {

  coll := db.Collection("users")

  u := new(User)
  if err = c.Bind(u); err != nil {
    return c.JSON(http.StatusInternalServerError, err)
  }

  result, err := coll.InsertOne(
    context.Background(),
    bson.NewDocument(
        bson.EC.String("email", u.Email),
        bson.EC.String("username", u.Username),
        bson.EC.String("password", u.Password),
    ),
  )
  if err != nil {
    return c.JSON(http.StatusInternalServerError, err)
  }

  return c.JSON(http.StatusCreated, result)
}

Cela renvoie quelque chose comme InsertedID: [90, 217, 85, 109, 184, 249, 162, 204, 249, 103, 214, 121] au lieu d'un ObjectID normal. Comment puis-je retourner le ObjectID réel du document nouvellement inséré?

7
kue

Un Collection.InsertOne() réussi renvoie un résultat de type mongo.InsertOneResult , qui est une structure enveloppant l'ID du document nouvellement inséré:

type InsertOneResult struct {
    // The identifier that was inserted.
    InsertedID interface{}
}

Le pilote officiel de MongoDB Go utilise le primitive.ObjectID type pour représenter les ObjectIds MongoDB. Ce type est un tableau d'octets simple:

type ObjectID [12]byte

Pour accéder à ce type, vous devez importer le package primitif .

import "go.mongodb.org/mongo-driver/bson/primitive"

InsertOneResult.InsertedID contiendra un type dynamique de primitive.ObjectID. Le primitive.ObjectID type ne définit pas de méthode de marshaling JSON personnalisée (n'implémente pas json.Marshaler ), ce qui signifie que lorsque le résultat est converti en JSON, les règles de marshaling par défaut seront utilisées, ce qui pour un tableau d'octets (pas de tranche) est ce que vous voyez: la représentation décimale des octets de l'ObjectID.

Vous ne devez pas convertir une valeur de type InsertOneResult en JSON, car elle (ou plutôt primitive.ObjectID lui-même) n'est pas "compatible JSON" (du moins pas dans la version actuelle).

Au lieu de cela, créez/encapsulez votre propre type où vous définissez à quoi vous voulez que le résultat ressemble en JSON, par exemple:

if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
    return c.JSON(http.StatusCreated, map[string]interface{}{
        "id": oid.String(),
    })
} else {
    // Not objectid.ObjectID, do what you want
}

Le code ci-dessus entraînerait une réponse JSON comme celle-ci:

{"id":"ObjectID(\"5ad9a913478c26d220afb681\")"}

Ou si vous voulez juste la représentation hexadécimale:

if oid, ok := result.InsertedID.(primitive.ObjectID); ok {
    return c.JSON(http.StatusCreated, map[string]interface{}{
        "id": oid.Hex(),
    })
}

Ce qui serait:

{"id":"5ad9a913478c26d220afb681"}
16
icza