Podobne artykuły na bazie wspólnych tagów w CakePHP 5
Jeśli chcesz pokazywać w blogu podobne artykuły, samo filtrowanie po tagach nie wystarczy. Trzeba jeszcze policzyć, ile tagów artykuły mają wspólnych, a potem posortować wyniki od najlepiej dopasowanych.
Problem z prostym matching()
Intuicyjnie jest zacząć od takiego zapytania:
$similarArticles = $this->Articles->find()
->matching('Tags', function ($q) use ($tagIds) {
return $q->where(['Tags.id IN' => $tagIds]);
})
->select(['id', 'title', 'slug'])
->where(['Articles.id !=' => $result->id])
->distinct()
->limit(3);
To działa tylko częściowo. Zapytanie zwraca artykuły, które mają przynajmniej jeden wspólny tag, ale nie rozróżnia, czy artykuł ma 1 wspólny tag, czy 5 wspólnych tagów.
Lepsza logika
Jeżeli chcesz najlepsze dopasowania, musisz:- znaleźć artykuły z przynajmniej jednym wspólnym tagiem,
- policzyć liczbę wspólnych tagów dla każdego artykułu,
- posortować wyniki malejąco po tej liczbie,
- dopiero potem wziąć kilka pierwszych rekordów.
Przykładowe zapytanie
Poniżej masz zapytanie, które możesz dopasować do swojej aplikacji:
$similarArticles = $this->Articles->find()
->select([
'Articles.id',
'Articles.title',
'Articles.slug',
'shared_tags' => $this->Articles->find()->func()->count('Tags.id')
])
->matching('Articles', function ($q) use ($tagIds) {
return $q->where(['Articles.id IN' => $tagIds]);
})
->where(['Articles.id !=' => $result->id])
->groupBy(['Articles.id', 'Articles.title', 'Articles.slug'])
->orderBy([
'shared_tags' => 'DESC',
'Articles.id' => 'DESC',
])
->limit(3);