Besoin d'aide ?

Vérifier si des enregistrements existent déjà ou s'il faut les créer.

  • Avatar de CinquièmeDimension
    Membre depuis :
    18/04/2019
    Messages :
    31

    Bonjour à tous,

    Il s'agit d'un projet sur lumen 5.7 où je dois, une fois par mois, importer un CSV contenant des données à mettre à jour. Ce CSV est un export d'une base de donnée d'un client et je ne peux pas changer le format ni les données.

    Le problème étant que, chaque mois les données du mois précédent sont toujours présentes dans le CSV je ne dois récupérer que les nouveaux enregistrements (il n'y a bien sûr pas la date d'enregistrement).

    Pour cela je passe sur chaque ligne et je vérifie avec une requête si l'entrée existe (l'entrée n'ayant pas de clé primaire, j'ai 3 champs à vérifier).

    // check if exist
    public static function exist($refco , $decl, $pdt){
    $exist = DB::table('produits')
    ->where('PD_CODE_REFCO', '=', $refco)
    ->where('PD_NUM_DECL', '=', $decl)
    ->where('PD_NUM_PDT', '=', $pdt)
    ->count();
    return $exist;
    }

    Cette solution fonctionne très bien. Seulement le fichier fait 11 000 lignes ! Et 11 000 requpêtes ca fait mal...

    J'ai pensé à faire un tableau avec toutes mes enregistrements (en n'incluant que les 3 champs qui m'intéressent pour alléger tout ça) pour ne faire qu'une seule requête. Mais je n'ai pas réussi à comparer ça avec ma ligne.
    Je crois que je peux faire une collection mais je ne sais pas trop utiliser une collection donc je ne sais pas si c'est la bonne solution. Sans compter que, array ou collection, ça demande beaucoup de ressource pour stocker ça et j'ai pas envie que le serveur plante.

    Quelqu'un a-t-il une piste pour moi ? :)

    (Je parle ici d'un CSV mais en réalité il y en a 6. Mais si je trouve la marche à suivre pour l'un, je trouve pour les autres)

    Merci d'avance :D

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2524

    Salut,

    La table produits n'a pas de clé primaire mais est-ce que les 3 champs concernés sont déclarés comme clé primaire composée ?

  • Avatar de CinquièmeDimension
    Membre depuis :
    18/04/2019
    Messages :
    31

    Salut bestmomo,

    La table produit que j'ai créée a un clé primaire mais je ne l'ai ajoutée que parceque ça m'embétait d'avoir une table sans ID. Mais pour l'import je ne m'en sers pas du tout car le CSV d'origine n'en a pas.

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2524

    Je me disais juste qu'une solution serait de déclarer les 3 champs comme clé composée et de passer par une requête INSERT IGNORE pour éviter automatiquement les duplications.

  • Avatar de CinquièmeDimension
    Membre depuis :
    18/04/2019
    Messages :
    31

    Merci de cette piste bestmomo.

    Je pense que mon problème ne serais pas réglé avec ça, étant donné que je pense qu'une requête serait quand même effectuée à chaque fois pour soit ajouter soit ignorer.

    Certes, ça m'éconnomise autant de requêtes qu'il y a de création par rapport à ma version (vu que je fais le test et l'ajout en deux requêtes) mais ce n'est utile que pour le premier import, car à partir du deuxième, l'ajout sera seulement de quelques produits et pas des milliers.

    Surtout que j'ai une quarantaine de champs qui peuvent quasiment tous être nuls dans cette table (et à peu de chose près pareil dans les autres tables) donc si je dois faire des conditions de partout dans ma requête ça risque d'être pas génial...

    Je pense que je vais essayer de creuser un peu plus la requête unique à comparer avec chaque ligne.
    Je vais essayer d'avoir dans un array la liste des enregistrements pour faire un test du genre if(!$array("val1","val2","val3")). Mais il faut que j'arrive a bien formater mon array..

  • Avatar de CinquièmeDimension
    Membre depuis :
    18/04/2019
    Messages :
    31

    C'est assez difficile car ma requete me retourne un objet dans lequel il y a un array, qui contient des objets. Avec un ->toArray() je peux me débarrasser de mon objet mère mais si j'essaie de convertir recursivement chaque objet présent dans mon array, je vais exhausted ma memoire ou au moins ralentir tout le processus...

    Il faudraut que j'arrive à un array [["val1","val2","val3"],["val1","val2","val3"],["val1","val2","val3"]]

  • Avatar de CinquièmeDimension
    Membre depuis :
    18/04/2019
    Messages :
    31

    Finalement j'ai fait comme suit:

    $list = Produits::list_exist();
    $list_array = $list->toArray();
    $z = 0;
    foreach ($list_array as $array){
    $list_array[$z] = array_values((array)$array);
    $z++;
    }
    $hit = [$val1,$val2,$val3];
    if(in_array($hit,$list_array)){
    echo 'oui test';
    }else{
    echo 'non test';
    }

    Mes 3 clés sont donc $val1, $val2 et $val3.
    Ca marche parfaitement et c'est surtout beaucoup plus rapide.

Vous ne pouvez pas répondre à ce sujet.