Golang официальный драйвер MongoDB ObjectID странное поведение - PullRequest
0 голосов
/ 10 февраля 2020

Я пытаюсь использовать официальный драйвер mongodb в golang и вижу что-то неожиданное.

Если у меня есть структура типа

type User struct {
    ID     primitive.ObjectID `json:"id" bson:"_id"`
    Name   string             `json:"name" bson:"name"`
    Email  string             `json:"email" bson:"email"`
}

, я создаю новый экземпляр этого с Name и Email, но без ID, ожидая, что БД заполнит его своим значением. Вместо этого он использует все нули и поэтому вторая и так далее вставки завершаются неудачно с

multiple write errors: [{write errors: [{E11000 duplicate key error collection: collection.name index: _id_ dup key: { : ObjectId('000000000000000000000000') }}]}, {<nil>}]

Если я использую *primitive.ObjectID, я получаю тот же класс ошибок только на null вместо нулей

multiple write errors: [{write errors: [{E11000 duplicate key error collection: collection.name index: _id_ dup key: { : null }}]}, {<nil>}]

Неважно, если я использую директиву omitempty или нет, тот же результат.

Если я опускаю поле ID полностью, это работает, но тогда моя структура не есть эти данные на нем.

Есть ли способ заставить БД обрабатывать идентификатор? Или ДОЛЖЕН Я явно вызываю функцию NewObjectID() в структуре?

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Неважно, если я использую директиву omitempty или нет, тот же результат.

omitempty тег на ID должен работать. Например:

type User struct {
    ID     primitive.ObjectID `json:"id" bson:"_id,omitempty"`
    Name   string             `json:"name" bson:"name"`
    Email  string             `json:"email" bson:"email"`
}

collection.InsertOne(context.Background(), User{Name:"Foo", Email:"Baz"})

Если вы не укажете тег omitepmty, то наблюдаемое вами поведение - это просто Go структурирует поведение; при этом, если какое-либо из полей структуры опущено, оно будет иметь нулевое значение. В этом случае, поскольку вы указали тип поля primitive.ObjectID , ObjectId('000000000000000000000000') - это нулевое значение.

Это причина, по которой вам нужно сначала сгенерировать значение перед вставкой, то есть:

collection.InsertOne(context.Background(), 
                     User{ ID: primitive.NewObjectID(), 
                           Name: "Foo", 
                           Email: "Bar"})

Есть ли способ заставить БД обрабатывать идентификатор?

Технически, это драйвер MongoDB, который автоматически генерирует ObjectId , если он не передан перед отправкой на сервер.

Вы можете попытаться использовать bson.M вместо структуры при вставке, чтобы пропустить поле _id, т.е.

collection.InsertOne(context.Background(), 
                     bson.M{"name":"Foo", "email":"Bar"})

Фрагмент кода написан выше используя mon go - go -драйвер v1.3.x

0 голосов
/ 12 февраля 2020

Структурный тег omitempty должен работать:

type User struct {
    ID     primitive.ObjectID `json:"id" bson:"_id,omitempty"`
    Name   string             `json:"name" bson:"name"`
    Email  string             `json:"email" bson:"email"`
}

Тип primitive.ObjectID реализует интерфейс bsoncodec.Zeroer, поэтому его следует исключить из документа, если это пустой идентификатор объекта (все 0 ) и драйвер сгенерирует новый для вас. Можете ли вы попробовать это и опубликовать вывод?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...