如何根据通用标签对相关文章进行排序?

时间:2019-06-10 11:40:46

标签: laravel eloquent

我有一个文章和标签表。每篇文章可以有多个标签。我想获取一篇文章的相关文章,并根据常见标签对结果进行排序。

// Tag Model
class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany(Article::class, 'taggable');
    }
}
// Article Model
class Article extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

我使用此代码获取相关文章,但我不知道如何基于更常见的标签对结果进行排序。

// And i 
$relatedArticle = Article::whereHas('tags', function($query) use ($article){
    $query->whereIn('name', $article->tags->pluck('name'));
})->where('id', '!=', $article->id)->take(10)->get();

1 个答案:

答案 0 :(得分:1)

在SQL中,所需的信息将通过以下方式检索(我不知道关联表的名称或外键和主键,因此如有必要,请进行更改):

SELECT articles.*, 
(
    SELECT COUNT(tags.id)
    FROM tags 
    JOIN articles_tags at ON tags.id = at.tag_id
    WHERE tags.name in ('A', 'B', 'C') /* acquired from $article->tags->pluck('name') */
    AND at.article_id = a.id
) as tags_in_common
FROM articles a 
WHERE articles.id != {$id} 
AND tags_in_common >= 1
ORDER BY tags_in_common DESC
LIMIT 10;

现在,使用queryBuilder,我们必须变得有点脏,但是看起来可能像这样:

//Fetches pairs: [article_id, numberInCommon]
$tagsInCommon = DB::table('tags')
    join('articles_tags', 'tags.id', '=', 'articles_tags.tag_id')
    ->select('articles_tags.article_id', DB::raw('COUNT(*) as numberInCommon'))
    ->whereIn('tags.name', $article->tags->pluck('name'))
    ->groupBy('articles_tags.article_id')

$relatedArticle = Article::
    ->joinSub($tagsInCommon, 'tags_in_common', function($join){
        $join->on('id', '=', 'tags_in_common.article_id')
    })
    ->where('id', '!=', $article->id)
    ->orderBy('tags_in_common.numberInCommon', 'desc')
    ->take(10)
    ->get();