Mongo-go-driver получает идентификатор объекта из результата вставки
После использования InsertOne
чтобы создать новый документ, когда я возвращаю результат, я получаю массив чисел, а не ObjectID
, В БД идентификатор генерируется нормально.
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)
}
Это возвращает что-то вроде InsertedID: [90, 217, 85, 109, 184, 249, 162, 204, 249, 103, 214, 121]
вместо нормального ObjectID
, Как я могу вернуть фактический ObjectID
из недавно вставленного документа?
1 ответ
Успешный Collection.InsertOne()
вернет результат типа mongo.InsertOneResult
, которая является структурой, заключающей в себе идентификатор вновь вставленного документа:
type InsertOneResult struct {
// The identifier that was inserted.
InsertedID interface{}
}
Официальный драйвер MongoDB Go использует objectid.ObjectID
тип для представления MongoDB ObjectIds. Этот тип представляет собой простой байтовый массив:
type ObjectID [12]byte
InsertOneResult.InsertedID
будет держать динамический тип objectid.ObjectID
, objectid.ObjectID
Тип не определяет пользовательский метод маршалинга JSON (не реализует json.Marshaler
), что означает, что при преобразовании результата в JSON будут использоваться правила маршалинга по умолчанию, которые для байтового массива (не для слайса) - это то, что вы видите: десятичное представление байтов ObjectID.
Вы не должны конвертировать значение типа InsertOneResult
в JSON, как это (точнее objectid.ObjectID
само по себе) не "JSON-friendly" (по крайней мере, в текущей версии).
Вместо этого создайте / оберните свой собственный тип, где вы определяете, как вы хотите, чтобы результат выглядел в JSON, например:
if oid, ok := result.InsertedID.(objectid.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\")"}
Или, если вы просто хотите шестнадцатеричное представление:
if oid, ok := result.InsertedID.(objectid.ObjectID); ok {
return c.JSON(http.StatusCreated, map[string]interface{}{
"id": oid.Hex(),
})
}
Который будет:
{"id":"5ad9a913478c26d220afb681"}