chg: [tag] Fetch event count for tags in one query

pull/6578/head
Jakub Onderka 2020-11-22 10:12:08 +01:00
parent 261d15265d
commit 7c7a8f2817
4 changed files with 95 additions and 45 deletions

View File

@ -1,6 +1,9 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property GalaxyCluster $GalaxyCluster
*/
class GalaxyClustersController extends AppController
{
public $components = array('Session', 'RequestHandler');
@ -99,46 +102,39 @@ class GalaxyClustersController extends AppController
$this->paginate['conditions']['AND'][] = $aclConditions;
$this->paginate['contain'] = array_merge($this->paginate['contain'], array('Org', 'Orgc', 'SharingGroup', 'GalaxyClusterRelation', 'TargetingClusterRelation'));
$clusters = $this->paginate();
$tagIds = array();
foreach ($clusters as $k => $cluster) {
$clusters[$k] = $this->GalaxyCluster->attachExtendByInfo($this->Auth->user(), $clusters[$k]);
$clusters[$k] = $this->GalaxyCluster->attachExtendFromInfo($this->Auth->user(), $clusters[$k]);
$tag = $this->GalaxyCluster->Tag->find('first', array(
'conditions' => array(
'LOWER(name)' => strtolower($cluster['GalaxyCluster']['tag_name']),
),
'fields' => array('id'),
'recursive' => -1,
'contain' => array('EventTag.event_id')
));
if (!empty($tag['Tag']['id'])) {
$clusters[$k]['GalaxyCluster']['event_count'] = $this->GalaxyCluster->Tag->EventTag->countForTag($tag['Tag']['id'], $this->Auth->user());
} else {
$clusters[$k]['GalaxyCluster']['event_count'] = 0;
}
$clusters[$k]['GalaxyCluster']['relation_counts'] = array(
'out' => count($clusters[$k]['GalaxyClusterRelation']),
'in' => count($clusters[$k]['TargetingClusterRelation']),
);
}
$tagIds = array();
if (!empty($clusters)) {
foreach ($clusters as $k => $v) {
$clusters[$k]['event_ids'] = array();
if (!empty($v['Tag'])) {
$tagIds[] = $v['Tag']['id'];
$clusters[$k]['GalaxyCluster']['tag_id'] = $v['Tag']['id'];
}
$clusters[$k]['GalaxyCluster']['synonyms'] = array();
foreach ($v['GalaxyElement'] as $element) {
$clusters[$k]['GalaxyCluster']['synonyms'][] = $element['value'];
}
if (isset($cluster['Tag']['id'])) {
$tagIds[] = $cluster['Tag']['id'];
$clusters[$k]['GalaxyCluster']['tag_id'] = $cluster['Tag']['id'];
}
$clusters[$k]['GalaxyCluster']['synonyms'] = array();
foreach ($cluster['GalaxyElement'] as $element) {
$clusters[$k]['GalaxyCluster']['synonyms'][] = $element['value'];
}
$clusters[$k]['GalaxyCluster']['event_count'] = 0; // real number is assigned later
}
$eventCountsForTags = $this->GalaxyCluster->Tag->EventTag->countForTags($tagIds, $this->Auth->user());
$this->loadModel('Sighting');
$csvForTags = $this->Sighting->tagsSparkline($tagIds, $this->Auth->user(), '0');
foreach ($clusters as $k => $cluster) {
if (!empty($cluster['GalaxyCluster']['tag_id']) && isset($csvForTags[$cluster['GalaxyCluster']['tag_id']])) {
$clusters[$k]['csv'] = $csvForTags[$cluster['GalaxyCluster']['tag_id']];
if (isset($cluster['GalaxyCluster']['tag_id'])) {
if (isset($csvForTags[$cluster['GalaxyCluster']['tag_id']])) {
$clusters[$k]['csv'] = $csvForTags[$cluster['GalaxyCluster']['tag_id']];
}
if (isset($eventCountsForTags[$cluster['GalaxyCluster']['tag_id']])) {
$clusters[$k]['GalaxyCluster']['event_count'] = $eventCountsForTags[$cluster['GalaxyCluster']['tag_id']];
}
}
}
$customClusterCount = $this->GalaxyCluster->fetchGalaxyClusters($this->Auth->user(), [

View File

@ -1,6 +1,9 @@
<?php
App::uses('AppController', 'Controller');
/**
* @property Tag $Tag
*/
class TagsController extends AppController
{
public $components = array('Security' ,'RequestHandler');
@ -81,10 +84,6 @@ class TagsController extends AppController
$tagList = array();
foreach ($paginated as $k => $tag) {
$tagList[] = $tag['Tag']['id'];
if (empty($passedArgsArray['exclude_statistics'])) {
$paginated[$k]['Tag']['count'] = $this->Tag->EventTag->countForTag($tag['Tag']['id']);
$paginated[$k]['Tag']['attribute_count'] = $this->Tag->AttributeTag->countForTag($tag['Tag']['id']);
}
if (!empty($tag['FavouriteTag'])) {
foreach ($tag['FavouriteTag'] as $ft) {
if ($ft['user_id'] == $this->Auth->user('id')) {
@ -111,13 +110,25 @@ class TagsController extends AppController
}
}
}
if (!$this->_isRest() && empty($passedArgsArray['exclude_statistics'])) {
$this->loadModel('Sighting');
$csvForTags = $this->Sighting->tagsSparkline($tagList, $this->Auth->user(), '0');
if (empty($passedArgsArray['exclude_statistics'])) {
$attributeCount = $this->Tag->AttributeTag->countForTags($tagList, $this->Auth->user());
// TODO: this must be called before `tagsSparkline`!
$eventCount = $this->Tag->EventTag->countForTags($tagList, $this->Auth->user());
if ($this->_isRest()) {
$csvForTags = []; // Sightings sparkline doesn't make sense for REST requests
} else {
$this->loadModel('Sighting');
$csvForTags = $this->Sighting->tagsSparkline($tagList, $this->Auth->user(), '0');
}
foreach ($paginated as $k => $tag) {
if (isset($csvForTags[$tag['Tag']['id']])) {
$paginated[$k]['Tag']['csv'] = $csvForTags[$tag['Tag']['id']];
$tagId = $tag['Tag']['id'];
if (isset($csvForTags[$tagId])) {
$paginated[$k]['Tag']['csv'] = $csvForTags[$tagId];
}
$paginated[$k]['Tag']['count'] = isset($eventCount[$tagId]) ? (int)$eventCount[$tagId] : 0;
$paginated[$k]['Tag']['attribute_count'] = isset($attributeCount[$tagId]) ? (int)$attributeCount[$tagId] : 0;
}
}
if ($this->_isRest()) {

View File

@ -180,12 +180,25 @@ class AttributeTag extends AppModel
}
}
public function countForTag($tag_id, $user)
/**
* @param array $tagIds
* @param array $user - Currently ignored for performance reasons
* @return array
*/
public function countForTags(array $tagIds, array $user)
{
return $this->find('count', array(
if (empty($tagIds)) {
return [];
}
$this->virtualFields['attribute_count'] = 'COUNT(AttributeTag.id)';
$counts = $this->find('list', [
'recursive' => -1,
'conditions' => array('AttributeTag.tag_id' => $tag_id)
));
'fields' => ['AttributeTag.tag_id', 'attribute_count'],
'conditions' => ['AttributeTag.tag_id' => $tagIds],
'group' => ['AttributeTag.tag_id'],
]);
unset($this->virtualFields['attribute_count']);
return $counts;
}
// Fetch all tags attached to attribute belonging to supplied event. No ACL if user not provided

View File

@ -1,6 +1,9 @@
<?php
App::uses('AppModel', 'Model');
/**
* @property Event $Event
*/
class EventTag extends AppModel
{
public $actsAs = array('Containable');
@ -157,12 +160,39 @@ class EventTag extends AppModel
return $tags;
}
public function countForTag($tag_id, $user)
/**
* @param int $tagId
* @param array $user
* @return int
*/
public function countForTag($tagId, array $user)
{
return $this->find('count', array(
$count = $this->countForTags([$tagId], $user);
return isset($count[$tagId]) ? (int)$count[$tagId] : 0;
}
/**
* @param array $tagIds
* @param array $user
* @return array Key is tag ID, value is event count that user can see
*/
public function countForTags(array $tagIds, array $user)
{
if (empty($tagIds)) {
return [];
}
$conditions = $this->Event->createEventConditions($user);
$conditions['AND']['EventTag.tag_id'] = $tagIds;
$this->virtualFields['event_count'] = 'COUNT(EventTag.id)';
$counts = $this->find('list', [
'recursive' => -1,
'conditions' => array('EventTag.tag_id' => $tag_id)
));
'contain' => ['Event'],
'fields' => ['EventTag.tag_id', 'event_count'],
'conditions' => $conditions,
'group' => ['EventTag.tag_id'],
]);
unset($this->virtualFields['event_count']);
return $counts;
}
public function getTagScores($eventId=0, $allowedTags=array(), $propagateToAttribute=false)