首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据匹配的分类术语数量显示相关帖子

如何根据匹配的分类术语数量显示相关帖子
EN

WordPress Development用户
提问于 2019-01-24 02:14:25
回答 3查看 3.6K关注 0票数 0

我有一个定制后类型的‘新闻’,其中有多个自定义分类‘新闻-类别’,‘新闻标签’。每个帖子包含4-8个‘新闻标签’和1个‘新闻类别’.

对于我目前的帖子,我想显示相关的文章,基于普通的‘新闻标签’术语添加到我当前的帖子,同时也匹配‘新闻类别’术语。

因此,我希望相关的帖子寻找相同的“新闻-类别”与大多数“新闻标签”的共同术语的帖子,并按降序显示它们。

如果我展示4个相关的职位:

  • 第一篇文章可能有5个“新闻标签”术语,
  • 第二篇文章可能有三个“新闻标签”术语,
  • 第三篇文章可能有两个“新闻标签”的共同术语,
  • 最后一篇文章可能有“新闻标签”一词的共同点。

它们都属于同一个“新闻类别”。

这样做是可能的吗?我一直在为这件事苦苦挣扎,所以我很感激你的帮助。

EN

回答 3

WordPress Development用户

回答已采纳

发布于 2019-01-25 09:08:00

让我们将问题分成三部分:从数据库中检索相关的帖子,对它们进行排序,并显示结果。

后检索

这是可以使用分类学参数WP_Query中提供的。

让我们首先检索当前帖子的类别并找到它们的ID:

代码语言:javascript
复制
$categories = get_the_terms( get_the_ID(), 'news-category' );

foreach ( $categories as $category ) {
                        $category_ids[] = $category->term_id;
                    }

我们对标签也是这样做的:

代码语言:javascript
复制
$tags = get_the_terms( get_the_ID(), 'news-tags' );

foreach ( $tags as $tag) {
                        $tag_ids[] = $tag->term_id;
                    }

然后,构建一组查询参数(稍后提供给WP_Query-call):

代码语言:javascript
复制
$related_args = array(
    'post_type'      => array(
        'news',
    ),
    'post_status'    => 'publish',
    'posts_per_page' => -1, // Get all posts
    'post__not_in'   => array( get_the_ID() ), // Hide current post in list of related content
    'tax_query'      => array(
        'relation' => 'AND', // Make sure to mach both category and term
        array(
            'taxonomy' => 'news-category',
            'field'    => 'term_id',
            'terms'    => $category_ids,
        ),
        array(
            'taxonomy' => 'news-tags',
            'field'    => 'term_id',
            'terms'    => $tag_ids,
        ),
    ),
);

最后,我们运行的查询为我们提供了一个

代码语言:javascript
复制
$related_all = new WP_Query( $related_args );

请注意,此查询检索与“筛选器”匹配的所有帖子,就像我们稍后进行排序一样。如果我们现在只查询4个帖子,它们可能不是最相关的。

Sidenote:上面的查询相当重,因为它(可能)检索了大量的帖子。当我为一个客户项目创建了一个相关的帖子部分(也是一个新闻部分)时,我按日期而不是相关性来订购。这允许您设置从数据库中检索的帖子数量的限制(在您的情况下,将-1更改为4,并将'orderby' => array( 'date' => 'DESC' )添加到$related_args__-数组中)。如果您想继续对重叠进行排序,我建议您在查询参数中添加一个日期筛选器,或者将结果的数量限制在某个有限的值上,然后从该值中检索最相关的帖子。

邮政订购

按照前面的步骤,$related_all是一个WP_Query-object。我们按如下方式访问实际的帖子,并将它们存储在$related_all_posts中:

代码语言:javascript
复制
$related_all_posts = $related_all->posts;

这为我们提供了一个更容易使用的数组。然后我们循环遍历数组中的所有结果。根据代码中的注释,在遍历结果时,我们找到与(相关的) post相关联的标记,查找它们的is,将其与前面找到的$tag_ids (主帖子)进行比较,并查看在使用array_intersect()时有多少重叠:

代码语言:javascript
复制
foreach($related_all_posts as $related_post){
    // Find all tags of the related post under consideration
    $related_post_tags = get_the_terms( $related_post->ID, 'news-tags' );
        foreach ( $related_post_tags as $related_post_tag ) {
            $related_tag_ids[] = $related_post_tag->term_id;    // Save their IDs in a query
        }

    // Find overlap with tags of main post (in $tag_ids) using array_intersect, and save that number in
    // an array that has the ID of the related post as array key.
    $related_posts_commonality[$related_post->ID] = count(array_intersect($related_tag_ids, $tag_ids));
}

然后,我们使用arsort()按值从高到低对最新的数组进行排序。

代码语言:javascript
复制
arsort($related_posts_commonality);

最后,我们仅使用array_slice()将其限制为四篇文章:

代码语言:javascript
复制
$related_posts_commonality = array_slice($related_posts_commonality, 0, 4);

您可以使用array_keys找到相关帖子的ID,例如:

代码语言:javascript
复制
$related_posts_IDs = array_keys($related_posts_commonality);

后显示

要真正显示这些帖子,你可以选择两条路线。您可以使用$related_posts_commonality数组循环WP_Query (即$related_all)的结果,将匹配的帖子(按正确的顺序)保存在一个新数组中,也可以使用对象再循环一次,以供显示。因为这不需要额外的查询,所以它可能是最有效的查询。然而,这也是一种痛苦。

因此,您也可以使用我们刚刚找到的ID ($related_posts_IDs)来运行另一个查询。

代码语言:javascript
复制
$related_sorted = WP_query(array('post__in' => $related_posts_IDs));

然后,您可以使用常规的循环播放 (while ($related_sorted->have_posts())等)来使用the_title()the_content()等函数来查看和显示结果。

票数 5
EN

WordPress Development用户

发布于 2021-04-23 20:47:39

由于给定的post类型共享相同的分类,常见的场景可能是根据所有分类的匹配项数(不管它们是多少或什么名称)找到相关的帖子,因此我为此创建了一个代码片段。这种方法不需要显式地定义要检查的自定义分类法(但如果需要的话也可以),而且还需要获得所有匹配项的总数,以便从最高到最低对相关的帖子进行排序。您可以修改代码段,以便只指定特定的分类法,或者更改最多应该返回多少相关帖子的限制。

这个片段有注释以供解释,但在模板中,该函数将接受当前的post ID,并返回相关帖子的post ID数组。在那里,您可以检查结果,并且假设至少找到了一些具有匹配项的其他帖子,您可以循环查看返回的相关帖子ID,然后使用ID显示关于每个帖子的任何信息(标题、链接到post等)。

基于OP问题的标题,我认为其他人可能会发现这是有用的。

下面是到代码片段的链接。

得到最近的帖子

若要在单个post模板中使用此操作,请执行以下操作:

代码语言:javascript
复制
$current_post_id = get_the_id();
$related_post_ids = get_related_posts($current_post_id);
// if we have related posts...
if ( !empty($related_post_ids) ) {
    foreach ( $related_post_ids as $post_id ) {
        echo '' . get_the_title($post_id) . '';
    }
} else {
    // No related posts found
}

helper函数的片段:

代码语言:javascript
复制
/**
 * A WordPress helper function that takes the ID of the current post
 * and returns the top three related posts ranked by highest number of taxonomy
 * terms in common with the current post. Alternately, you can modify lines 26-33
 * to exclude certain taxonomies so that we only check for terms in specific taxonomies 
 * to determine the related posts. To include up to the top X related posts instead of
 * up to three, you can modify lines 149-150.
 *
 * In your template to make use of this function you would do something like...
 *
 * $current_post_id = get_the_id();
 * $related_post_ids = get_related_posts($current_post_id);
 * 
 */

function get_related_posts($current_post_id)
    {   
        // Get the post type we're dealing with based on the current post ID.
        $post_type = get_post_type($current_post_id);

        // Get all taxonomies of the specified post type of the current post.
        $taxonomies = [];
        $taxonomy_objects = get_object_taxonomies( $post_type, 'objects' );
        foreach($taxonomy_objects as $taxonomy) {
            // If you want to only check against certain taxonomies, modify this section as needed
            // to set conditions for which taxonomies should be excluded or included. Below is just an example.
            // if ($taxonomy->name !== 'post_format' && $taxonomy->name !== 'post_tag') {
            //     array_push($taxonomies, $taxonomy);
            // }
          
            // By default, we will check against all taxonomies.
            array_push($taxonomies, $taxonomy);
        }

        // Get all the posts of the specified post type,
        // excluding the current post, so that we can compare these
        // against the current post.
        $other_posts_args = array(
            'posts_per_page'   => -1,
            'post_type'      => $post_type,
            'post__not_in'   => array($current_post_id),
        );
        $other_posts = new WP_Query( $other_posts_args );

        wp_reset_postdata();

        // We will create an object for each matching post that will include
        // the ID and count of the number of times it matches any taxonomy term with the current post.
        // Later, when we create those, they will get pushed to this $matching_posts array.
        $matching_posts = array();

        // If we have other posts, loop through them and
        // count matches for any taxonomy terms in common.
        if($other_posts->have_posts()) {

            foreach($taxonomies as $taxonomy) {

                // Get the term IDs of terms for the current post
                // (the post presumably displaying as a single post
                // back in our template, for which were finding related posts).
                $current_post_terms = get_the_terms($current_post_id, $taxonomy->name);


                // Only continue if the current post actually has some terms for this taxonomy.
                if($current_post_terms !== false) {

                    foreach($other_posts->posts as $post) {

                        // Get the term IDs of terms for this taxonomy
                        // for the other post we are currently looping over.
                        $other_post_terms = get_the_terms($post->ID, $taxonomy->name);

                        // Check that other post has terms and only continue if there
                        // are terms to compare.
                        if($other_post_terms !== false) {

                            $other_post_term_IDs = array();
                            $current_post_term_IDs = array();

                            // Get term IDs from each term in the current post.
                            foreach($current_post_terms as $term) {
                                array_push($current_post_term_IDs, $term->term_id);
                            }

                            // Get term IDs from each term in the other post.
                            foreach($other_post_terms as $term) {
                                array_push($other_post_term_IDs, $term->term_id);
                            }

                            if( !empty($other_post_term_IDs) && !empty($current_post_term_IDs) ) {
                                
                                // Collect the matching term IDs for the terms the posts have in common.
                                $match_count = sizeof(array_intersect($other_post_term_IDs, $current_post_term_IDs));
                                
                                // Get the ID of the other post to use to identify and store this post
                                // in our results.
                                $post_ID = $post->ID;

                                if ($match_count > 0) {

                                    // Assume post not added previously.
                                    $post_already_added = false;

                                    // If posts have already been added to our matches
                                    // then check to see if we already added this post.
                                    if(!empty($matching_posts)) {
        
                                        foreach($matching_posts as $post) {
                                            // If this post was added previously then let's increment the count
                                            // for our new matching terms.
                                            if (isset($post->ID) && $post->ID == $post_ID) {
                                                $post->count += $match_count;
                                                // Switch this to true for the check we perform below.
                                                $post_already_added = true;
                                            }
                                        }
                                        
                                        // If never found a post with same ID in our $matching_posts
                                        // list then create a new entry associated with this post and add it.
                                        if ($post_already_added === false) {
                                            $new_matching_post = new stdClass();
                                            $new_matching_post->ID = $post_ID;
                                            $new_matching_post->count = $match_count;
                                            array_push($matching_posts, $new_matching_post);
                                        }
                                    } else {
                                        // If no posts have been added yet to $matching_posts then this will be the first.
                                        $new_matching_post = new stdClass();
                                        $new_matching_post->ID = $post_ID;
                                        $new_matching_post->count = $match_count;
                                        array_push($matching_posts, $new_matching_post);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            
            if(!empty($matching_posts)) {
                // Sort the array in order of highest count for total terms in common
                // (most related to least).
                usort($matching_posts, function($a, $b) {
                    return strcmp($b->count, $a->count);
                });

                // Just take the top 3 most related
                $most_related = array_slice($matching_posts, 0, 3);
                
                // Get the IDs of most related posts.
                $matching_posts = array_map(function($obj) {
                    return $obj->ID;
                }, $most_related);
            }
   
        } 

        return $matching_posts;


    }
票数 1
EN

WordPress Development用户

发布于 2022-08-23 08:10:12

我以Brams为例,但需要在两个点对代码进行调整,以便按预期运行。

( 1)每个相关_post的清除数组$related_tag_ids

代码语言:javascript
复制
foreach($related_all_posts as $related_post){
    // Find all tags of the related post under consideration
    $related_post_tags = get_the_terms( $related_post->ID, 'news-tags' );
    $related_tag_ids = array();
    foreach ( $related_post_tags as $related_post_tag ) {
        $related_tag_ids[] = $related_post_tag->term_id;    // Save their IDs in a query
    }

    // Find overlap with tags of main post (in $tag_ids) using array_intersect, and save that number in
    // an array that has the ID of the related post as array key.
    $related_posts_commonality[$related_post->ID] = count(array_intersect($related_tag_ids, $tag_ids));
}

2)数组片,$preserve_keys设置为true

代码语言:javascript
复制
$related_posts_commonality = array_slice($related_posts_commonality, 0, true);
票数 0
EN
页面原文内容由WordPress Development提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://wordpress.stackexchange.com/questions/326497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档