我正在使用Lumen框架v5.8(与Laravel相同)
我有一个命令,用于读取大XML(400Mo)并从此文件中的数据更新数据库中的数据,这是我的代码:
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
因此,我必须在XML中找到每个DescriptorUI
元素,该值对应于我的类mesh_id
的{{1}}属性。
因此,通过Condition
我得到了Condition对象。
之后,我需要更新$conditionId = Condition::where('mesh_id', $meshId)->first();
=> Condition
的子级。因此,我只获取元素ConditionTranslation
并更新DescriptorName
的{{1}}字段
在脚本结尾处,您会看到name
,当我运行命令时,该值每次都会增加,直到脚本运行得非常慢...再也不会结束。
如何优化此脚本?
谢谢!
编辑:Laravel有没有一种方法可以预更新多个对象,最后只保存一次所有对象?就像Symfony的ConditionTranslation
方法
答案 0 :(得分:0)
有ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}