Improved related tags suggestions

This commit is contained in:
Marcin Kurczewski 2014-05-18 21:51:04 +02:00
parent 79f9ab9950
commit 4f33d0bd5b

View file

@ -16,51 +16,35 @@ class TagSearchService extends AbstractSearchService
return []; return [];
$parentTagId = $parentTagEntity->getId(); $parentTagId = $parentTagEntity->getId();
//get tags that appear with selected tag along with their occurence frequency $punishCommonTags = false;
$stmt = (new Sql\SelectStatement)
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->setGroupBy('tag.id')
->setOrderBy('post_count', Sql\SelectStatement::ORDER_DESC)
->setCriterion(new Sql\ExistsFunctor((new Sql\SelectStatement)
->setTable('post_tag pt2')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('pt2.post_id', 'post_tag.post_id'))
->add(new Sql\EqualsFunctor('pt2.tag_id', new Sql\Binding($parentTagId)))
)));
$rows1 = []; $rows = self::getSiblingTagsWithOccurences($parentTagId);
foreach (Database::fetchAll($stmt) as $row) unset($rows[$parentTagId]);
$rows1[$row['id']] = $row;
//get the same tags, but this time - get global occurence frequency if ($punishCommonTags)
$stmt = (new Sql\SelectStatement)
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->setCriterion(Sql\InFunctor::fromArray('tag.id', Sql\Binding::fromArray(array_keys($rows1))))
->setGroupBy('tag.id');
$rows2 = [];
foreach (Database::fetchAll($stmt) as $row)
$rows2[$row['id']] = $row;
$rows = [];
foreach ($rows1 as $i => $row)
{ {
//multiply own occurences by two because we are going to subtract them $rowsGlobal = self::getGlobalOccurencesForTags(array_keys($rows));
$row['sort'] = $row['post_count'] * 2;
//subtract global occurencecount
$row['sort'] -= isset($rows2[$i]) ? $rows2[$i]['post_count'] : 0;
if ($row['id'] != $parentTagId) foreach ($rows as $i => &$row)
$rows []= $row; {
//multiply own occurences by two because we are going to subtract them
$row['sort'] = $row['post_count'] * 2;
//subtract global occurencecount
$row['sort'] -= isset($rowsGlobal[$i]) ? $rowsGlobal[$i]['post_count'] : 0;
}
}
else
{
foreach ($rows as $i => &$row)
{
$row['sort'] = $row['post_count'];
}
} }
usort($rows, function($a, $b) { return intval($b['sort']) - intval($a['sort']); }); usort($rows, function($a, $b)
{
return intval($b['sort']) - intval($a['sort']);
});
return TagModel::spawnFromDatabaseRows($rows); return TagModel::spawnFromDatabaseRows($rows);
} }
@ -77,4 +61,43 @@ class TagSearchService extends AbstractSearchService
->setLimit(1, 0); ->setLimit(1, 0);
return TagModel::spawnFromDatabaseRow(Database::fetchOne($stmt)); return TagModel::spawnFromDatabaseRow(Database::fetchOne($stmt));
} }
private static function getSiblingTagsWithOccurences($parentTagId)
{
$stmt = (new Sql\SelectStatement)
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->setGroupBy('tag.id')
->setOrderBy('post_count', Sql\SelectStatement::ORDER_DESC)
->setCriterion(new Sql\ExistsFunctor((new Sql\SelectStatement)
->setTable('post_tag pt2')
->setCriterion((new Sql\ConjunctionFunctor)
->add(new Sql\EqualsFunctor('pt2.post_id', 'post_tag.post_id'))
->add(new Sql\EqualsFunctor('pt2.tag_id', new Sql\Binding($parentTagId)))
)));
$rows = [];
foreach (Database::fetchAll($stmt) as $row)
$rows[$row['id']] = $row;
return $rows;
}
private static function getGlobalOccurencesForTags($tagIds)
{
$stmt = (new Sql\SelectStatement)
->setTable('tag')
->addColumn('tag.*')
->addColumn(new Sql\AliasFunctor(new Sql\CountFunctor('post_tag.post_id'), 'post_count'))
->addInnerJoin('post_tag', new Sql\EqualsFunctor('post_tag.tag_id', 'tag.id'))
->setCriterion(Sql\InFunctor::fromArray('tag.id', Sql\Binding::fromArray($tagIds)))
->setGroupBy('tag.id');
$rows = [];
foreach (Database::fetchAll($stmt) as $row)
$rows[$row['id']] = $row;
return $rows;
}
} }