Здравствуйте коллеги!
Заказчик требует реализации метода, который бы выполнял клонирование некоторых записей.
Например:
На примере АЗС
Есть сеть заправок, их количество достигает 61 000 тыс.
Каждая заправка имеет ряд предоставляемых услуг.
Понятное дело, что это продажа разных видов топлива.
У каждой заправки свой перечень видов, это выглядит так:
Заправка А - 17
Заправка Б - 18
INSERT INTO `features` (`id`, `name`, `type`, `value`, `organization_id`) VALUES
(36, 'Заправка', 'enum', NULL, 17),
(71, 'Заправка', 'enum', NULL, 18);
INSERT INTO `features_values` (`id`, `feature_id`, `name`) VALUES
(111, 71, 'Аи-92'),
(115, 36, 'Аи-95'),
(113, 36, 'Аи-98'),
(112, 71, 'Дт');
Заказчик выбирает любую компанию и вносит корректив в перечень текущей компании.
И внимание! Что бы была опция для распространения корректива на все компании
Например всем 61 000 добавить условно "Пропан"
Для этого я написал функцию, ниже есть её реализация.
$features_repository->cloning($feature->getName(), $item);
Привожу пример функции.
Функция работает корректно, за исключением того, что его некоторая часть, достаточно дорога.
/**
* @Rest\Route(
* path="/features.edit",
* methods={"POST"}
* )
* @param ObjectManager $manager
* @param Request $request
* @param RestMessage $restMessage
* @return JsonResponse
* @throws RestException
* @throws DBALException
*/
public function edit(ObjectManager $manager, Request $request, RestMessage $restMessage)
{
/** @var FeatureRepository $features_repository */
$features_repository = $manager->getRepository("App:Feature");
$feature = $features_repository->findOneBy([
"id" => $request->get("feature_id", 0)]
);
if (!is_object($feature)) {
RestError::exception(RestCode::RECORD_NOT_FOUND);
}
switch ($request->get("type", false)) {
case "bool":
{
$feature->setType("bool");
$feature->setName($request->get("name"));
$feature->setValue($request->get("value"));
foreach ($feature->getValues() as $value) {
$manager->remove($value);
$manager->flush();
}
$manager->persist($feature);
break;
}
case "text":
{
$feature->setType("text");
$feature->setName($request->get("name"));
$feature->setValue($request->get("value"));
foreach ($feature->getValues() as $value) {
$manager->remove($value);
$manager->flush();
}
$manager->persist($feature);
break;
}
case "enum":
{
$feature->setType("enum");
$feature->setName($request->get("name"));
$feature->setValue($request->get(null));
/** @var FeatureValue $old_fv */
$not_persist = [];
foreach ($feature->getValues() as $old_fv) {
$remove_old_fv = true;
foreach ($request->get("value", []) as $new_value) {
if ($new_value == $old_fv->getName()) {
$remove_old_fv = false;
$not_persist[] = $new_value;
break;
}
}
if ($remove_old_fv) {
$manager->remove($old_fv);
$manager->flush();
}
}
foreach ($request->get("value", []) as $item) {
foreach ($not_persist as $np) {
if ($item == $np) continue 2;
}
$feature_value = new FeatureValue();
$feature_value->setName($item);
$feature_value->setFeature($feature);
$feature->getValues()->add($feature_value);
$manager->persist($feature_value);
// Дорогой mysql запрос
if ($request->get("cloning", false)) {
$features_repository->cloning($feature->getName(), $item);
}
}
break;
}
default:
{
RestError::exception(RestCode::REQUEST_WITH_INVALID_PARAMETERS);
}
}
$manager->flush();
return $restMessage->success("Ok");
}
Обратите внимание на комментарий "Дорогой mysql запрос"
Функция клонирования
/**
* @param string $feature_name
* @param string $feature_value_name
* @throws DBALException
*/
public function cloning(string $feature_name, string $feature_value_name)
{
$conn = $this->getEntityManager()->getConnection();
$sql = "
INSERT IGNORE INTO features_values (`feature_id`, `name`) (
SELECT DISTINCT f.id, :feature_value_name
FROM features f
LEFT JOIN features_values fv
ON f.id = fv.feature_id
WHERE f.name = :feature_name AND f.`type` = :feature_type
);
";
$stmt = $conn->prepare($sql);
$stmt->execute([
"feature_type" => EnumFeatureType::ENUM_TYPE,
"feature_name" => $feature_name,
"feature_value_name" => $feature_value_name
]);
}
Схема
Самое главное, что таблица
features_values будет содержать сотни миллионов записей ((
Что делать????
Форкать процесс, пусть себе живет сутки?
Ресурсы: