WordPress

wp query – Jak skutecznie znaleźć „duplikaty” postów, w których tytuły są różne, używając metadanych do dopasowania postów?

  • 22 maja, 2023
  • 5 min read
wp query – Jak skutecznie znaleźć „duplikaty” postów, w których tytuły są różne, używając metadanych do dopasowania postów?


Serwis, nad którym pracuję, zbiera informacje o taśmach filmowych. A 'film' to niestandardowy typ postu. Każdy „film” to jeden post.

Użytkownicy masowo przesyłają filmy z różnych źródeł. Z tego powodu niektóre filmy są przesyłane dwukrotnie, z różnych źródeł.

Chciałbym znaleźć każdy film przesłany dwa razy i połączyć informacje zawarte w tych dwóch filmach w jeden.

Problem polega na tym, że informacje o każdym filmie nie zawsze są wprowadzane w ten sam sposób. Czasami tytuł ma inną pisownię lub jest po prostu inaczej wymieniony, albo na przykład wpis pola metadanych, takiego jak „firma_produkcyjna”, ma inną pisownię.

Napisałem kod, który bierze jeden film i przechodzi przez całą bazę danych, szukając podobnych wpisów. Mój kod działa dobrze. Problem polega na tym, że jest NIESAMOWICIE powolny. Muszę kilka razy odświeżać stronę, żeby chociaż przebrnąć przez porównanie jednego filmu z drugim w bazie danych (z 200 tys. filmów).

Zastanawiam się, czy istnieje sposób przepisania lub ponownego przemyślenia tego problemu, abym mógł napisać bardziej wydajny system. Rozważam włączenie się wp_cron i uruchamianie tego co 5 minut przez całą wieczność, ale nie wydaje się to świetnym długoterminowym, wydajnym rozwiązaniem.

Warto przeczytać!  Wtyczka Wordpress standardowa funkcjonalność AJAX

Oto mój kod – używam taksonomii o nazwie „notaduplicate” do filtrowania wyników, więc pętla nie pokazuje tych samych wyników za każdym razem. Ustawiłem identyfikator postu każdego filmu, który nie jest duplikatem warunków filmu.

Jak mogę uczynić ten kod bardziej wydajnym, który może przetwarzać więcej danych jednocześnie?

<?php
$film_a_args = array(
  'numberposts' => 1,
  'post_type'   => 'film'
);
$all_films = get_posts( $film_a_args );        //this gets the first film, I'd like to be able to run more than one at a time, but this function is so expensive i can only do 1
foreach($all_films as $single_film){
    $film_a_post_id=$single_film->ID;
    $title=get_the_title($film_a_post_id);
    $film_b_args = array(
        'post_type' => 'film',
        'posts_per_page'=> 1000,
        'tax_query'=> array(
          array(
            'taxonomy'=>'notaduplicate',  //notaduplicate says that this film has been checked against another film, and it is not a duplicate
            'field'=>'slug',
            'terms'=>$film_a_post_id,
            'operator'=>'NOT IN',
          ),
        ),
    );
    // The Query
    $the_query = new WP_Query( $film_b_args );

    // The Loop
    if ( $the_query->have_posts() ) {
      $i=0;
      while ( $the_query->have_posts() ) {
          $the_query->the_post();
          $film_b_post_id=get_the_ID();
          $film_a_permalink=get_the_permalink($film_a_post_id);
          $film_b_permalink=get_the_permalink($film_b_post_id);
          if($film_a_post_id==$film_b_post_id){
              wp_set_post_terms( $film_a_post_id, $film_a_post_id, 'notaduplicate',  true); //if the film sees itself
              echo 'film set terms not a duplicate with itself';
          }else{
              $metafields=array('film_title','series','duration_in_minutes','production_company','format','color','sound','online_copy_link','wikipedia_link','imdb_link');
              foreach($metafields as $metafield){
                  $film_a_metafield=get_post_meta(  $film_a_post_id,  $key = $metafield, $single = true );
                  $film_b_metafield=get_post_meta(  $film_b_post_id,  $key = $metafield, $single = true );
                  if($film_a_metafield){
                      if($film_a_metafield == $film_b_metafield){
                          //if the two films have the same metafield
                          //and the meta field is an 'auspicious' one, add 5 to $i
                          if($metafield=='film_title'||$metafield=='duration_in_minutes'||$metafield=='online_copy_link'||$metafield=='wikipedia_link'||$metafield=='imdb_link'){
                              $i=$i+5;
                          }else $i++; //else add 1 to $i
                      }
                  }
              }
              if($i<5){     //if $i meets the 'duplicate threshold'
                  $i=0;
                  //update taxonomy 'not a duplicate with post id for both films' 
                  //this sets a term (of the other films id) for each film, so they will cycle through search.
                  wp_set_post_terms( $film_a_post_id, $film_b_post_id, 'notaduplicate',  true); 
                  wp_set_post_terms( $film_b_post_id, $film_a_post_id, 'notaduplicate',  true);
                  echo '<li>' ,'Film B: ','<a href=" get_the_title() .'</a>',' Post Id: '.$film_b_post_id.'Has been checked against: ', '</li>';
                  echo '<li>' ,'Film A (Original Film): ','<a href=".$film_a_permalink.">'. get_the_title($film_a_post_id) .'</a>',' Post Id: '.$film_a_post_id. '</li>';
                  echo 'and taxonomy has been updated';
                  echo '<hr>';
              }else{
                //here i will write the code to merge the films together into one post
                //for now i just have a little ranking system
                  echo '<h3>'.get_the_title($film_b_post_id).' has '.$i.' duplicate points.','</h3>';
                  echo '<ul>';
                  echo '<li>' ,'Film A (Original Film): ','<a href=".$film_a_permalink.">'. get_the_title($film_a_post_id) .'</a>',' Post Id: '.$film_a_post_id. '</li>';
                  echo '<li>' ,'Film B (Possible Duplicate): ','<a href=" get_the_title() .'</a>',' Post Id: '.$film_b_post_id. '</li>';
                  if($i>=7){
                      echo 'This is most likely a duplicate';
                  }else{
                      echo 'This is probably a duplicate';
                  }
                  echo 'End Of Possible Duplicate: ','<a href=" get_the_title() .'</a>','<hr>';
                  $i=0;
                  echo '</ul>';
              }   
          }
      }
    } else {
    // no posts found
    }
    /* Restore original Post Data */
    wp_reset_postdata();
}
?>

Dzięki!

Warto przeczytać!  system plików - Jak zapisać plik tekstowy i zapisać go w folderze do późniejszego pobrania?


Źródło