Я пытаюсь сохранить относительно большую часть данных в MongoDB, используя BulkWrite
для нескольких вставок. Данные поступают из внешнего ресурса, поэтому я не могу полностью контролировать их содержимое. Количество записей данных может достигать 15 тыс. И более для единичной массовой операции. Вот часть моего кода:
$bulk = new BulkWrite();
foreach ($data as $id => $item) {
$bulk->update(
['id' => $item['id']],
$item,
['upsert' => true]
);
}
try {
$result = $mongo->getManager()->executeBulkWrite(
'db.collection',
$bulk,
new WriteConcern(WriteConcern::MAJORITY)
);
} catch (\MongoDB\Driver\Exception\UnexpectedValueException $e) {
// we have a problem here
}
Время от времени я сталкиваюсь с такими исключениями:
[MongoDB \ Driver \ Exception \ UnexpectedValueException] Получено недопустимое значение UTF-8, сериализующее ‘ 8’
Я не хочу фильтровать все эти данные, потому что это повлияет на производительность. Можно ли получить точную запись, по которой произошло это исключение? Насколько я знаю, эти данные не доступны из UnexpectedValueException
объект и его предыдущее исключение, которое также UnexpectedValueException
,
Единственное решение, которое я нашел, — это добавление блока try / catch с ручным вызовом метода кодирования BSON. К сожалению, значение bson нельзя использовать в качестве входных данных для массового обновления / операции вставки. Итак, это \MongoDB\BSON\fromPHP
Вызов избыточен, однако позволяет обнаружить «плохую» запись. Вот код:
$bulk = new BulkWrite();
foreach ($data as $id => $item) {
try {
$bson = \MongoDB\BSON\fromPHP($item);
} catch (UnexpectedValueException $e) {
foreach ($item as $key => $value) {
if (is_string($value)) {
$item[$key] = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
} else {
$item[$key] = $value;
}
}
}
$bulk->update(
['id' => $item['id']],
$item,
['upsert' => true]
);
}
Других решений пока нет …