2016-05-25 3 views
3

私は3重ピボットテーブルを可能にし、バッチ挿入をサポートしないlaravelコンポーザパッケージを使用しています。だから私は3つのテーブルからの各IDが私のトリプルピボットテーブル内の一致を持っていることを確認するために各配列をループしているつもりです。私はうまくいきましたが、関数をリファクタリングする方法についていくつか提案したいので、たくさんのネストループを持つ必要はありません。私は配列マップの使用について考えていました。入れ子3深いforeachループをリファクタリングする方法

答えて

4

これは、Eloquentを使用して解決するのは難しい問題です。現在は不可能かもしれません。最初にわかったように、それは3つの方法のピボットテーブルをサポートしていません。第2に、サポートを追加するために使用しているパッケージは、そのレコードにアイテムを継続的に添付して、同期がないためデータベースに膨大なデータ複製を作成するように見えます。第3に、テーブル内のフィールドにユニークなインデックスを追加して一意のレコードを適用する場合、insert ignoreクエリはサポートされていません。

これを念頭において、raw SQLを使用すると便利です。しかし、SQLでは狂ったことは何もないので、この場合は問題ないと思います。

まず、データベースレベルでデータの整合性を強制する必要があります。これを行う方法は、ピボットテーブルがどのように構造化されているかによって異なります。自動増分主キーであるこのテーブルの列がすでにidの場合、リンクしようとしている3つのテーブルのIDを含む3つの列に一意のキーを追加する必要があります。 idまたは他の主キーがすでに存在しない場合は、これらの3つの列を含む複合主キーを設定できます。

既に重複しているレコードがある場合、これは失敗します。それらの重複を削除してキーを再追加するだけでよいはずです。

これまで述べてきたことを踏まえて、私はバルクインサートを使用するように関数をリファクタリングしました。

function addKeyPhraseToPivotTable($ids) { 

    $locations = Location::where('account_id', self::$items[0]['account_id'])->get(); 
    $urls = Url::where('account_id', self::$items[0]['account_id'])->get(); 

    $deletes = []; 
    if ($locations->count() > 0 && $urls->count() > 0) { 
     foreach ($ids as $keyPhraseId) { 
      foreach ($locations as $location) { 
       foreach ($urls as $url) { 
        $deletes[] = [ 
         'location' => $location->id, 
         'key' => $keyPhraseId, 
         'url' => $url->id, // Not sure what the ID is of this item, might need to change it. 
        ]; 
       } 
      } 
     } 
    } 

    $sql = 'insert ignore into accounts (location_id, key_phrase_id, url_id) values '; 

    foreach ($deletes as $i => $delete) { 
     $sql .= $i == 0 ? '' : ','; 
     $sql .= sprintf('(%s, %s, %s)', $delete['location'], $delete['key'], $delete['url']); 
    } 

    DB::unprepared($sql); 
} 

これは、あなたが持っている各レコードを挿入しなければならないし、挿入を無視しているので、複製を挿入しようとすると壊れません。

DB::unprepared()は、作成した行の数を返すので、挿入しようとしたアイテムの数が重複していることを知ることができます。しかし、on duplicate key updateを追加した場合、MySQLは更新されて挿入されていない行ごとに2行を返しますので、その場合はおそらく役に立たないでしょう。

+0

おかげで、フローを1つずつ挿入するのではなく、スピードアップする必要があります。 –

関連する問題