2
votes

Comment éviter les doublons à insérer

J'utilise Laravel 5.6.29

CharmFlag::updateOrCreate(
          ['post_id' => $postId, 'charm_id' => $charm_id],
          [
              'gif_flag' => $gif_flag,
          ]
 );

mais dans la base de données je peux voir des enregistrements comme entrez la description de l'image ici

Maintenant, on peut voir qu'il y a des enregistrements en double pour charm_id = 18604 et charm_id = 18605 , mais selon ce que j'ai codé, cela ne devrait pas arriver.

Mettre à jour

Également changé le code en

Schema::create('charm_flags', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('post_id');
    $table->unsignedInteger('charm_id');
    $table->boolean('gif_flag')->default(0);

    $table->timestamps();
    $table->foreign('post_id')->references('post_id')->on('posts');
    $table->foreign('charm_id')->references('charm_id')->on('base_charms');
});


16 commentaires

vous obtenez juste -> premier () pas tous multiples


@DanyalSandeelo J'obtiens peu d'enregistrements corrects et peu de doublons, si vous pouvez remarquer la combinaison 3260-18604 et 3260-18605 .


@Tarasovych orWhere ne fonctionnera jamais, j'ai besoin d'une combinaison de post_id et charm_id pour être unique et en bricolant la condition fonctionne bien.


Voulez-vous éviter d'enregistrer des enregistrements en double dans la base de données?, Car comme je le vois, la valeur created_at pour les entrées en double est la même


CharmFlag :: where ('post_id', '=', $ postId) -> where ('charm_id', '=', $ charm_id) -> first (); cela ne renverrait qu'un seul enregistrement


@RahulMeshram oui, je veux éviter les entrées en double dans la base de données pour lesquelles la combinaison post_id et charm_id est la même.


Ensuite, créez une migration pour modifier cette table avec une combinaison unique, ce sera mieux pour vous. $ table-> unique (array ('charm_id', 'post_id')); comme ceci.


Ainsi, vous pouvez CharmFlag :: where ('post_id', '=', $ postId) -> where ('charm_id', '=', $ charm_id) -> count () , si valeur est supérieur à 0, vous accédez au cas else


Je conseille d'utiliser FormRequest dans ce cas, afin d'éviter de futures duplications. Vous pouvez utiliser la règle unique pour la validation.


@RahulMeshram Je n'essaye pas de récupérer l'enregistrement unique, je veux éviter une entrée en double dans la table, comme mon code semble correct, j'aimerais savoir comment cette exception peut se produire.


Exactement, mon pote, l'extrait que j'ai partagé avec vous évitera toute autre entrée à enregistrer dans la base de données.


@Tarasovych isEmpty () faisant la même chose que count () == 0 .


@RahulMeshram au lieu d'utiliser un tableau, puis-je utiliser le modèle?


link c'est la manière la plus sûre de le faire. Et au niveau du modèle, il vous suffit de détecter cette exception. Votre compagnon d'appel, je peux vous recommander le meilleur moyen.


@RahulMeshram qui semble bien, mais ne peut pas changer la migration maintenant, car cette soeur vit maintenant avec des millions de données.


@RahulMeshram enfin j'ai fait ce que vous aviez suggéré, changé la structure de table en utilisant une migration de modification, merci, cela signifie que toutes ces fonctions n'ont aucune garantie, la structure de la base de données doit être exactement ce dont nous avons besoin.


5 Réponses :


7
votes

Vous n'avez pas besoin de vérifier isEmpty , vous pouvez utiliser les méthodes firstOrNew () ou updateOrCreate ()

$charmFlag = CharmFlag::updateOrCreate(['post_id' => $postId, 'charm_id' => $charm_id]);
$charmFlag->gif_flag = $gif_flag;
$charmFlag->save();


10 commentaires

Merci pour cela, mais y a-t-il un problème avec mon code?


Cela ne résout pas non plus mon problème, obtenant toujours des enregistrements en double.


J'espère que si vous mettez à jour votre table en utilisant une migration comme celle-ci $ table-> unique (['post_id', 'charm_id']); cela résoudra votre problème


cela peut supprimer le mauvais enregistrement à l'étape actuelle, c'est pourquoi je ne change pas la migration.


L'ajout d'une contrainte unique ne modifiera pas les enregistrements existants. L'ajout de la contrainte échouera s'il existe des enregistrements qui ne correspondent pas à cette contrainte. Vous devriez vraiment avoir au moins un identifiant unique par ligne, peut-être la combinaison de postID et charmID.


@Qirel oui la combinaison de postID et charmID est unique, mais il y a d'autres colonnes à côté de gif_flag et ces deux, ce que je peux faire est de garder la première entrée de chaque entrée en double et de supprimer la dernière, mais tout aussi important est d'éviter de nouvelles entrées en double.


@Sethu firstOrNew n'insérera que s'il n'existe pas, mais updateOrCreate se mettra à jour s'il existe et s'il n'existe pas, il s'insérera, donc plus tard, mon exigence est de ne pas obtenir de doublon.


@PrafullaKumarSahu J'ai déjà suggéré updateOrCreate et je suis content que vous ayez la solution :)


@Sethu oui je sais, mais j'ai juste pensé à vous le faire savoir, j'ai également voté pour votre réponse car je l'ai trouvé utile, en m'attendant simplement à ne pas être dupliqué avec updateOrCreated, déjà supprimé les données en double déjà existantes et en attendant que de nouvelles données soient insérées pour vérifier si cela fonctionne bien car l'application est en ligne.


@Sethu mais toujours en double, vient d'obtenir 20/25 nouveaux enregistrements avec 4 doublons.



4
votes

S'il existe un post_id et un charm_id , définissez le gif_flag . Si aucun modèle correspondant n'existe, créez-en un.

Vous pouvez essayer comme ceci:

CharmFlag::updateOrCreate(
    ['post_id' => $postId, 'charm_id' => $charm_id],
    ['gif_flag' => $gif_flag]
);

Cela améliore également les performances de votre code.


16 commentaires

Il fait la même chose que mon code, donc cela ne résout pas mon problème, mais j'aimerais vraiment savoir comment cela améliorera mes performances?


Au lieu d'exécuter plusieurs requêtes, vous en exécutez une et utilisez une variable à la place. Bien que la solution consistant à remplacer votre code actuel par celui de la réponse de Sethu soit probablement la façon la plus propre et la meilleure de s'y prendre.


vous pouvez essayer ceci, c'est le meilleur moyen de mettre à jour ou de créer s'il n'existe pas.


@Qirel J'ai mis à jour mon code, mais j'ai toujours des entrées en double!


@PrafullaKumarSahu: Avez-vous effacé votre base de données après avoir modifié le code?


@svikramjeet non, je ne peux pas effacer ma base de données, je recherche de nouvelles entrées et je trouve de nouvelles entrées en double.


CharmFlag :: updateOrCreate (['post_id' => $ postId, 'charm_id' => $ charm_id], ['gif_flag' => $ gif_flag]);


Cela ne devrait pas autoriser les entrées en double car clairement cette méthode sera mise à jour (si l'enregistrement existe) sinon créer un nouveau


@prafullaKumarSahu, je suis incapable de comprendre pourquoi le code n'a pas affecté la réponse


@SurenderSinghRawat c'est déroutant pour moi aussi, les gens travaillent sur cette application et je garde les yeux sur les nouvelles entrées et il semble que rien ne résout le problème.


@SurenderSinghRawat oui j'ai juste essayé cette commande ainsi que php artisan cache: clear mais ne semble pas changer le résultat.


@PrafullaKumarSahu, en fait c'est un tableau croisé dynamique pour cette vérification ma réponse stackoverflow.com/questions/55718378/...


@SurenderSinghRawat non ce n'est pas un tableau croisé dynamique, c'est un nouveau modèle, j'ai donné des exemples de données en sélectionnant des colonnes car c'était trop long.


veuillez également mettre à jour la classe et la migration dans votre question.


Laissez-nous continuer cette discussion dans le chat .


Il y a une préférence pour firstOrNew , mais après avoir parcouru la documentation, je dois dire que updateOrCreate est plus préférable dans mon cas.



1
votes

Les chances de créer des doublons se trouvent dans la première condition, -> get () -> isEmpty () cela ne semble pas fonctionner.

Pouvez-vous mettre à jour votre requête comme ceci et voir. p>

if (CharmFlag::where('post_id', '=', $postId)->where('charm_id', '=', $charm_id)->first()) {

  CharmFlag::create([
      'post_id' => $postId,
      'charm_id' => $charm_id,
      'gif_flag' => $gif_flag
  ]);

} else {

  $charmFlag = CharmFlag::where('post_id', '=', $postId)->where('charm_id', '=', $charm_id)->first();
  $charmFlag->gif_flag = $gif_flag;
  $charmFlag->save();

  // you can also use below for update. this is faster and efficient.
  /* 
   CharmFlag::updateOrCreate(
    ['post_id' => $postId, 'charm_id' => $charm_id],
    ['gif_flag' => $gif_flag]
  );  
  */

}


0 commentaires

1
votes

essayez ceci:

$charmFlag = CharmFlag::where([['post_id',$postId],['charm_id',$charmId]])->first();

if($charmFlag)
    $charmFlag->gifFlag = $gif_flag;
else
{
    $charmFlag = new CharmFlag();
    $charmFlag->post_id = $postId;
    $charmFlag->charm_id = $charm_id;
    $charmFlag->gif_flag = $gif_flag;
}
$charmFlag->save();


0 commentaires

1
votes

Aucune des réponses publiées n'a fonctionné pour moi, donc basée sur des suggestions de commentaires

  1. Suppression de toutes les entrées en double avec

DELETE FROM charm_flags WHERE id IN (SELECT * FROM (SELECT MAX (n.id) FROM charm_flags n GROUP BY post_id, charm_id HAVING COUNT (*)> 1) x)

  1. Génération d'une nouvelle migration pour modifier la table charm_flags

Schema :: table ('charm_flags', function (Blueprint $ table) { $ table-> unique (["post_id", "charm_id"]); });

s'il existe une meilleure solution, j'aimerais l'apprendre.


0 commentaires