web-dev-qa-db-ja.com

Mongo-go-driverは挿入結果からオブジェクトIDを取得します

InsertOneを使用して新しいドキュメントを作成した後、結果を返すと、ObjectIDではなく数値の配列が返されます。 DBでは、IDは正常に生成されています。

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

これは通常のObjectIDではなくInsertedID: [90, 217, 85, 109, 184, 249, 162, 204, 249, 103, 214, 121]のようなものを返します。新しく挿入されたドキュメントから実際のObjectIDを返すにはどうすればよいですか?

7
kue

Collection.InsertOne() が成功すると、タイプ mongo.InsertOneResult の結果が返されます。これは、新しく挿入されたドキュメントのIDをラップする構造体です。

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

公式のMongoDB Goドライバーは primitive.ObjectID タイプを使用してMongoDB ObjectIdを表します。この型は単純なバイト配列です:

type ObjectID [12]byte

このタイプにアクセスするには、 primitive package をインポートする必要があります。

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

InsertOneResult.InsertedIDprimitive.ObjectIDの動的タイプを保持します。 primitive.ObjectIDタイプはカスタムJSONマーシャリングメソッドを定義しません( json.Marshaler は実装していません)。つまり、結果がJSONに変換されると、デフォルトのマーシャリングルールが使用されますこれは、バイト配列(スライスではない)の場合、ObjectIDのバイトの10進数表現です。

タイプInsertOneResultの値はJSONに変換しないでください。これは(またはprimitive.ObjectID自体が)「JSONフレンドリー」ではないためです(少なくとも現在のバージョンでは)。

代わりに、結果をJSONでどのように表示するかを定義する独自のタイプを作成/ラップします。次に例を示します。

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
}

上記のコードは、次のようなJSON応答になります。

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

または、16進表記だけが必要な場合:

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

どちらになるでしょう:

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