Маршал и умаршал БСОН - PullRequest
       40

Маршал и умаршал БСОН

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

TL; DR: Предоставляет ли драйвер MongoDB функцию для маршалирования и демаршализации одного поля документа?

Это довольно простой вопрос, но вот некоторый контекст:

У меня есть работник, ответственный за синхронизацию данных между двумя отдельными базами данных. Когда он получает сообщение о событии, сигнализирующее о том, что какой-то документ должен синхронизироваться c, он выбирает документ в первичной базе данных и реплицирует его в другую (это совершенно другая база данных, а не набор реплик).

Дело в том, что я не знаю полной структуры этого документа, поэтому, чтобы сохранить данные, я должен разархивировать этот документ на карте map[string]interface{} или bson.M, которая работает таким же образом. Но это похоже на большие издержки, чтобы разархивировать все эти данные, которые я даже не использую, только для того, чтобы перенести их обратно в другую базу данных.

Поэтому я подумал о создании структуры, которая будет просто хранить двоичные файлы значение этого документа, без выполнения какого-либо маршала или демаршала для уменьшения накладных расходов, например:

type Document = map[string]Field

type Field struct {
    Type  bsontype.Type
    Value []byte
}

func (f Field) MarshalBSONValue() (bsontype.Type, []byte, error) {
    return f.Type, f.Value, nil
}

func (f *Field) UnmarshalBSONValue(btype bsontype.Type, value []byte) error {
    f.Type = btype
    f.Value = value
    return nil
}

С помощью этой структуры я действительно могу уменьшить объем данных, которые будут проанализированы, но теперь я Мне нужно вручную распаковать одно значение в этом документе, которое мне нужно использовать.

Поэтому мне интересно, будет ли драйвер MongoDB иметь такую ​​функцию, как:

// Hypothetical function to get the value of a BSON
var status string
if err := decodeBSON(doc['status'].Type, doc['status'].Value, &status); err != nil {
    return err
}

И

// Hypothetical function to set the value of a BSON
createdAt, err := encodeBSON(bsontype.Date, time.Now())
if err != nil {
    return err
}

doc["createdAt"] = Field{Type: bsontype.Date, Value: createdAt}

Как мне этого добиться?

1 Ответ

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

Тип Field в вашем коде эквивалентен типу bson.RawValue драйвера. Переключившись на RawValue, вы можете декодировать отдельные поля с помощью метода RawValue.Unmarshal и кодировать поля с помощью bson.MarshalValue, который возвращает два компонента (тип и данные), которые необходимы для создания нового RawValue.

Пример того, как вы можете использовать эти методы для изменения поля на основе его исходного значения: тип Field в вашем коде эквивалентен типу bson.RawValue драйвера. Переключившись на RawValue, вы можете декодировать отдельные поля с помощью метода RawValue.Unmarshal и кодировать поля с помощью bson.MarshalValue, который возвращает два компонента (тип и данные), которые вам нужны для создания нового RawValue.

Пример того, как вы можете изменить поле в зависимости от его исходного значения без отмены разбивки всех полей исходного документа: https://gist.github.com/divjotarora/06c5188138456070cee26024f223b3ee

...