Как отсортировать статьи по общим тегам? - PullRequest
2 голосов
/ 10 июня 2019

У меня есть таблица статей и тегов.Каждая статья может иметь несколько тегов.Я хочу получить соответствующие статьи для статьи и отсортировать результаты по общим тегам.

// 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 Ответ

1 голос
/ 11 июня 2019

В 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...