From ebcc4de58c4b65a71b1307b962c73cf8f8276324 Mon Sep 17 00:00:00 2001 From: "florian.azizian" <florian.azizian@maarch.org> Date: Mon, 19 Oct 2020 12:32:50 +0200 Subject: [PATCH] FEAT #13271 TIME 2 optimize search timing --- .../search/controllers/SearchController.php | 69 +++++++++---------- src/app/search/models/SearchModel.php | 66 ++++++++++++++++++ 2 files changed, 98 insertions(+), 37 deletions(-) create mode 100644 src/app/search/models/SearchModel.php diff --git a/src/app/search/controllers/SearchController.php b/src/app/search/controllers/SearchController.php index 2e52b169270..2e8c69d7bd4 100644 --- a/src/app/search/controllers/SearchController.php +++ b/src/app/search/controllers/SearchController.php @@ -37,6 +37,7 @@ use Resource\models\ResourceContactModel; use Resource\models\ResourceListModel; use Resource\models\UserFollowedResourceModel; use Respect\Validation\Validator; +use Search\models\SearchModel; use Slim\Http\Request; use Slim\Http\Response; use SrcCore\controllers\AutoCompleteController; @@ -119,24 +120,16 @@ class SearchController $searchData[] = $nonSearchableStatuses; } - $db = new DatabasePDO(); - $db->beginTransaction(); - $query = "DROP TABLE IF EXISTS search_tmp_".$GLOBALS['id'].";"; - $db->query($query); - $query = "CREATE TEMPORARY TABLE search_tmp_".$GLOBALS['id']." (res_id bigint, priority character varying(16), type_id bigint, destination character varying(50), status character varying(10), category_id character varying(32)) ON COMMIT DROP;"; - $db->query($query); - - $resourcesBeforeFilters = "SELECT res_id, priority, type_id, destination, status, category_id FROM res_view_letterbox WHERE " . implode(' AND ', $searchWhere); - $query = "INSERT INTO search_tmp_".$GLOBALS['id']." (res_id, priority, type_id, destination, status, category_id)" . $resourcesBeforeFilters; - $db->query($query, $searchData); + // Begin transaction for temporarySearchData + DatabaseModel::beginTransaction(); + SearchModel::createTemporarySearchData(['where' => $searchWhere, 'data' => $searchData]); $filters = []; if (empty($queryParams['filters'])) { $filters = SearchController::getFilters(['body' => $body]); } - $db->commitTransaction(); - $searchClause = SearchController::getFiltersClause(['body' => $body, 'searchWhere' => $searchWhere, 'searchData' => $searchData]); + $searchClause = SearchController::getFiltersClause(['body' => $body]); if (empty($searchClause)) { return $response->withJson(['resources' => [], 'count' => 0, 'allResources' => []]); } @@ -157,16 +150,17 @@ class SearchController $orderBy = str_replace(['chrono', 'typeLabel', 'creationDate', 'category', 'destUser', 'processLimitDate', 'entityLabel'], ['order_alphanum(alt_identifier)', 'type_label', 'creation_date', 'category_id', 'dest_user', 'process_limit_date', 'entity_label'], $queryParams['order']); $orderBy = !in_array($orderBy, ['order_alphanum(alt_identifier)', 'status', 'subject', 'type_label', 'creation_date', 'category_id', 'dest_user', 'process_limit_date', 'entity_label', 'priority']) ? ['creation_date'] : ["{$orderBy} {$order}"]; - $allResources = ResModel::getOnView([ - 'select' => ['res_id as "resId"'], - 'where' => $searchWhere, - 'data' => $searchData, - 'orderBy' => $orderBy + $allResources = SearchModel::getTemporarySearchData([ + 'select' => ['res_id'], + 'where' => $searchWhere, + 'data' => $searchData, + 'orderBy' => $orderBy ]); + DatabaseModel::commitTransaction(); if (empty($allResources[$offset])) { return $response->withJson(['resources' => [], 'count' => 0, 'allResources' => [], 'filters' => $filters]); } - $allResources = array_column($allResources, 'resId'); + $allResources = array_column($allResources, 'res_id'); $resIds = []; $order = 'CASE res_id '; @@ -1197,10 +1191,11 @@ class SearchController private static function getFiltersClause(array $args) { - ValidatorModel::notEmpty($args, ['searchWhere', 'searchData']); - ValidatorModel::arrayType($args, ['body', 'searchWhere', 'searchData']); + ValidatorModel::arrayType($args, ['body']); - $body = $args['body']; + $body = $args['body']; + $searchWhere = []; + $searchData = []; if (!empty($body['filters'])) { if (!empty($body['filters']['doctypes']) && is_array($body['filters']['doctypes'])) { @@ -1211,8 +1206,8 @@ class SearchController } } if (!empty($doctypes)) { - $args['searchWhere'][] = 'type_id in (?)'; - $args['searchData'][] = $doctypes; + $searchWhere[] = 'type_id in (?)'; + $searchData[] = $doctypes; } } if (!empty($body['filters']['categories']) && is_array($body['filters']['categories'])) { @@ -1223,8 +1218,8 @@ class SearchController } } if (!empty($categories)) { - $args['searchWhere'][] = 'category_id in (?)'; - $args['searchData'][] = $categories; + $searchWhere[] = 'category_id in (?)'; + $searchData[] = $categories; } } if (!empty($body['filters']['priorities']) && is_array($body['filters']['priorities'])) { @@ -1236,11 +1231,11 @@ class SearchController } if (!empty($priorities)) { if (in_array(null, $priorities)) { - $args['searchWhere'][] = '(priority in (?) OR priority is NULL)'; + $searchWhere[] = '(priority in (?) OR priority is NULL)'; } else { - $args['searchWhere'][] = 'priority in (?)'; + $searchWhere[] = 'priority in (?)'; } - $args['searchData'][] = $priorities; + $searchData[] = $priorities; } } if (!empty($body['filters']['statuses']) && is_array($body['filters']['statuses'])) { @@ -1252,11 +1247,11 @@ class SearchController } if (!empty($statuses)) { if (in_array(null, $statuses)) { - $args['searchWhere'][] = '(status in (?) OR status is NULL)'; + $searchWhere[] = '(status in (?) OR status is NULL)'; } else { - $args['searchWhere'][] = 'status in (?)'; + $searchWhere[] = 'status in (?)'; } - $args['searchData'][] = $statuses; + $searchData[] = $statuses; } } if (!empty($body['filters']['entities']) && is_array($body['filters']['entities'])) { @@ -1268,11 +1263,11 @@ class SearchController } if (!empty($entities)) { if (in_array(null, $entities)) { - $args['searchWhere'][] = '(destination in (?) OR destination is NULL)'; + $searchWhere[] = '(destination in (?) OR destination is NULL)'; } else { - $args['searchWhere'][] = 'destination in (?)'; + $searchWhere[] = 'destination in (?)'; } - $args['searchData'][] = $entities; + $searchData[] = $entities; } } if (!empty($body['filters']['folders']) && is_array($body['filters']['folders'])) { @@ -1283,13 +1278,13 @@ class SearchController } } if (!empty($folders)) { - $args['searchWhere'][] = 'res_id in (select distinct res_id from resources_folders where folder_id in (?))'; - $args['searchData'][] = $folders; + $searchWhere[] = 'res_id in (select distinct res_id from resources_folders where folder_id in (?))'; + $searchData[] = $folders; } } } - return ['searchWhere' => $args['searchWhere'], 'searchData' => $args['searchData']]; + return ['searchWhere' => $searchWhere, 'searchData' => $searchData]; } private static function getFilters(array $args) diff --git a/src/app/search/models/SearchModel.php b/src/app/search/models/SearchModel.php new file mode 100644 index 00000000000..cf209ef9c62 --- /dev/null +++ b/src/app/search/models/SearchModel.php @@ -0,0 +1,66 @@ +<?php + +/** + * Copyright Maarch since 2008 under licence GPLv3. + * See LICENCE.txt file at the root folder for more details. + * This file is part of Maarch software. + * + */ + +/** + * @brief Search Template Model + * @author dev@maarch.org + */ + +namespace Search\models; + +use SrcCore\models\DatabaseModel; +use SrcCore\models\DatabasePDO; +use SrcCore\models\ValidatorModel; + +class SearchModel +{ + public static function createTemporarySearchData(array $args) + { + $database = new DatabasePDO(); + + $query = "DROP TABLE IF EXISTS search_tmp_".$GLOBALS['id'].";"; + $database->query($query); + $query = "CREATE TEMPORARY TABLE search_tmp_".$GLOBALS['id']." ( + res_id bigint, + priority character varying(16), + type_id bigint, + destination character varying(50), + status character varying(10), + category_id character varying(32), + alt_identifier character varying(255), + subject text, + creation_date timestamp without time zone, + dest_user INTEGER, + process_limit_date timestamp without time zone, + entity_label character varying(255), + type_label character varying(255) + ) ON COMMIT DROP;"; + $database->query($query); + + $selectValues = "res_id, priority, type_id, destination, status, category_id, alt_identifier, subject, creation_date, dest_user, process_limit_date, entity_label, type_label"; + $temporaryData = "SELECT " . $selectValues . " FROM res_view_letterbox WHERE " . implode(' AND ', $args['where']); + $query = "INSERT INTO search_tmp_".$GLOBALS['id']." (" . $selectValues . ")" . $temporaryData; + $database->query($query, $args['data']); + } + + public static function getTemporarySearchData(array $args) + { + ValidatorModel::arrayType($args, ['select', 'where', 'data', 'orderBy']); + + $data = DatabaseModel::select([ + 'select' => $args['select'], + 'table' => ['search_tmp_' . $GLOBALS['id']], + 'where' => $args['where'], + 'data' => $args['data'], + 'order_by' => $args['orderBy'] + ]); + + return $data; + } +} -- GitLab