Enhance bookmark queries (#1182)

Don't query tags per bookmark separately
This commit is contained in:
Marcel Klehr 2020-08-23 17:50:11 +02:00 committed by GitHub
parent 6cf7ffccf3
commit 41e91392f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 4 deletions

View File

@ -158,7 +158,9 @@ class BookmarkController extends ApiController {
$array['folders'] = array_map(function (Folder $folder) {
return $this->toExternalFolderId($folder->getId());
}, $array['folders']);
$array['tags'] = $this->tagMapper->findByBookmark($bookmark->getId());
if (!isset($array['tags'])) {
$array['tags'] = $this->tagMapper->findByBookmark($bookmark->getId());
}
return $array;
}

View File

@ -67,6 +67,21 @@ class BookmarkMapper extends QBMapper {
$this->tagMapper = $tagMapper;
}
/**
* Magic to use BookmarkWithTags if possible
* @param array $row
* @return Entity
*/
protected function mapRowToEntity(array $row): Entity {
$hasTags = array_first($row, function ($field) {
return preg_match('#tag#i', $field, $matches) !== false;
}, false);
if ($hasTags !== false) {
return BookmarkWithTags::fromRow($row);
}
return \call_user_func($this->entityClass .'::fromRow', $row);
}
/**
* Find a specific bookmark by Id
@ -188,14 +203,18 @@ class BookmarkMapper extends QBMapper {
if ($params->getConjunction() === 'or') {
$connectWord = 'OR';
}
if (count($filters) === 0) {
return;
}
// select tags
if ($dbType === 'pgsql') {
$tags = $qb->createFunction('array_to_string(array_agg(' . $qb->getColumnName('t.tag') . "), ',')");
} else {
$tags = $qb->createFunction('GROUP_CONCAT(' . $qb->getColumnName('t.tag') . ')');
}
$qb->selectAlias($tags, 'tags');
if (count($filters) === 0) {
return;
}
$filterExpressions = [];
$otherColumns = ['b.url', 'b.title', 'b.description'];
foreach ($filters as $filter) {
@ -217,6 +236,20 @@ class BookmarkMapper extends QBMapper {
$qb->having($filterExpression);
}
/**
* @param $qb
*/
private function _selectTags($qb): void {
$dbType = $this->config->getSystemValue('dbtype', 'sqlite');
$qb->leftJoin('b', 'bookmarks_tags', 't', $qb->expr()->eq('t.bookmark_id', 'b.id'));
if ($dbType === 'pgsql') {
$tags = $qb->createFunction('array_to_string(array_agg(' . $qb->getColumnName('t.tag') . "), ',')");
} else {
$tags = $qb->createFunction('GROUP_CONCAT(' . $qb->getColumnName('t.tag') . ')');
}
$qb->selectAlias($tags, 'tags');
}
/**
* @param string $userId
* @param QueryParameters $params
@ -238,6 +271,7 @@ class BookmarkMapper extends QBMapper {
))
->andWhere($qb->expr()->eq('b.available', $qb->createPositionalParameter(false, IQueryBuilder::PARAM_BOOL)));
$this->_selectTags($qb);
$this->_queryBuilderSortAndPaginate($qb, $params);
return $this->findEntities($qb);
@ -260,6 +294,7 @@ class BookmarkMapper extends QBMapper {
->where($qb->expr()->eq('tr.parent_folder', $qb->createPositionalParameter($folderId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('tr.type', $qb->createPositionalParameter(TreeMapper::TYPE_BOOKMARK)));
$this->_selectTags($qb);
$this->_queryBuilderSortAndPaginate($qb, $params);
return $this->findEntities($qb);
@ -288,6 +323,14 @@ class BookmarkMapper extends QBMapper {
))
->andWhere($qb->expr()->eq('t.tag', $qb->createPositionalParameter($tag)));
$dbType = $this->config->getSystemValue('dbtype', 'sqlite');
if ($dbType === 'pgsql') {
$tags = $qb->createFunction('array_to_string(array_agg(' . $qb->getColumnName('t.tag') . "), ',')");
} else {
$tags = $qb->createFunction('GROUP_CONCAT(' . $qb->getColumnName('t.tag') . ')');
}
$qb->selectAlias($tags, 'tags');
$this->_queryBuilderSortAndPaginate($qb, $params);
return $this->findEntities($qb);
@ -309,6 +352,14 @@ class BookmarkMapper extends QBMapper {
$qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId))
));
$dbType = $this->config->getSystemValue('dbtype', 'sqlite');
if ($dbType === 'pgsql') {
$tags = $qb->createFunction('array_to_string(array_agg(' . $qb->getColumnName('t.tag') . "), ',')");
} else {
$tags = $qb->createFunction('GROUP_CONCAT(' . $qb->getColumnName('t.tag') . ')');
}
$qb->selectAlias($tags, 'tags');
return $qb;
}

View File

@ -0,0 +1,40 @@
<?php
namespace OCA\Bookmarks\Db;
/**
* Class Bookmark
*
* @package OCA\Bookmarks\Db
* @method getTags
*/
class BookmarkWithTags extends Bookmark {
protected $tags;
public static $columns = ['id', 'url', 'title', 'description', 'lastmodified', 'added', 'clickcount', 'last_preview', 'available', 'archived_file', 'user_id', 'tags'];
public static $fields = ['id', 'url', 'title', 'description', 'lastmodified', 'added', 'clickcount', 'lastPreview', 'available', 'archivedFile', 'userId', 'tags'];
public static function fromArray($props) {
$bookmark = new Bookmark();
foreach ($props as $prop => $val) {
$bookmark->{'set' . $prop}($val);
}
return $bookmark;
}
public function __construct() {
parent::__construct();
}
public function toArray(): array {
$array = [];
foreach (self::$fields as $field) {
if ($field === 'tags') {
$array[$field] = $this->{$field} === ''? [] : explode(',',$this->{$field});
continue;
}
$array[$field] = $this->{$field};
}
return $array;
}
}