Publicaciones con al menos 3 etiquetas de una lista de etiquetas

12

Por ejemplo, hay las etiquetas { foo , bar , chocolate , mango , hammock , leaf }

Me gustaría encontrar todas las publicaciones con al menos 3 de estas etiquetas .

Una publicación con etiquetas { foo , mango , vannilla , nuts , leaf } coincidirá porque tiene { foo , mango , leaf } - así que menos 3 etiquetas del conjunto de etiquetas necesarias.

Por lo tanto, estaría en la lista de las publicaciones coincidentes.

¿Hay una forma sencilla de hacerlo sin hacer varios bucles en todas las publicaciones?

    
pregunta Cedric 15.06.2013 - 18:36

3 respuestas

8

La respuesta a continuación es simplificada y podría extenderse para verificar si cualquiera de las publicaciones tiene 3 etiquetas coincidentes antes de enviar la lista. Usando una consulta y asumiendo que tienes al menos una publicación con 3 etiquetas coincidentes:

//List of tag slugs
$tags = array('foo', 'bar', 'chocolate', 'mango', 'hammock', 'leaf');

$args = array(
    'tag_slug__in' => $tags
    //Add other arguments here
);

// This query contains posts with at least one matching tag
$tagged_posts = new WP_Query($args);

echo '<ul>';
while ( $tagged_posts->have_posts() ) : $tagged_posts->the_post();
   // Check each single post for up to 3 matching tags and output <li>
   $tag_count = 0;
   $tag_min_match = 3;
   foreach ( $tags as $tag ) {
      if ( has_tag( $tag ) && $tag_count < $tag_min_match ) {
         $tag_count ++;
      }
   }
   if ($tag_count == $tag_min_match) {
      //Echo list style here
      echo '<li><a href="'. get_permalink() .'" title="'. get_the_title() .'">'. get_the_title() .'</a></li>';
   }
endwhile;
wp_reset_query();
echo '</ul>';

EDITAR: Al ajustar la variable $tag_min_match se establecerá el número de coincidencias.

    
respondido por el stellarcowboy 15.06.2013 - 20:34
2

Aquí hay una forma de hacerlo:

Dado un conjunto de 5 etiquetas, {a, b, c, d, e} :

1) En PHP, genere todos los subconjuntos posibles que contengan 3 elementos, sin repetición:

{a, b, c}
{a, b, d}
{a, b, e}
{a, c, d}
{a, c, e}
{b, c, d}
{b, c, e}
{c, d, e}

2) Convierta esos subconjuntos en una consulta de taxonomía masiva:

$q = new WP_Query( array(
  'tax_query' => array(
    'relation' => 'OR',
    array(
      'terms' => array( 'a', 'b', 'c' ),
      'field' => 'slug',
      'operator' => 'AND'
    ),
    array(
      'terms' => array( 'a', 'b', 'd' ),
      'field' => 'slug',
      'operator' => 'AND'
    ),
    ...
  )
) );
    
respondido por el scribu 16.06.2013 - 00:35
1

El enfoque de sprclldr es el que usé. En cuanto al bucle while, aquí está lo que usé en su lugar:

$relatedPosts = $tagged_posts->posts;
$indexForSort = array();

for ($i = count($relatedPosts) - 1; $i >= 0; $i--) {
  $relatedPostTags = get_tags($relatedPosts[$i]->ID);
  //get the ids of each related post
  $relatedPostTags = $this->my_array_column($relatedPostTags, 'term_id');
  $relatedPostTagsInPostTag = array_intersect($tags, $relatedPostTags);
  $indexForSort[$i] = count($relatedPostTagsInPostTag);
}

//sort by popularity, using indexForSort
array_multisort($indexForSort, $relatedPosts, SORT_DESC);

Luego tomo los primeros puestos:

$a_relatedPosts = array_slice($relatedPosts, 0, $this->numberRelatedPosts);

my_array_column es una función similar a la array_column de PHP 5,5:

  protected function my_array_column($array, $column) {
    if (is_array($array) && !empty($array)) {
      foreach ($array as &$value) {
        //it also get the object's attribute, not only array's values
        $value = is_object($value) ? $value->$column : $value[$column];
      }
      return $array;
    }
    else
      return array();
  }

No responde la pregunta inicial (pero resuelve mi problema de raíz ), como  : si no hay publicaciones relacionadas con 3 etiquetas comunes, esto dará todas las mismas publicaciones.

    
respondido por el Cedric 16.06.2013 - 21:58

Lea otras preguntas en las etiquetas