From c897f2c9c60de447937422f2c7acb00ed8f9edb1 Mon Sep 17 00:00:00 2001 From: Gilles Crettenand Date: Wed, 20 May 2015 15:22:51 +0200 Subject: [PATCH] always load details in the same query --- lib/AudioBook.php | 389 +++++++++++-------------------------------- lib/BookSearch.php | 6 + mobile.netbiblio.php | 31 ++-- 3 files changed, 114 insertions(+), 312 deletions(-) diff --git a/lib/AudioBook.php b/lib/AudioBook.php index e28ba3f..564fe30 100644 --- a/lib/AudioBook.php +++ b/lib/AudioBook.php @@ -12,6 +12,14 @@ function convertMSChar($src) /** * AudioBook is mapped on a Notice from NetBiblio * + * @property string id + * @property string sql_id + * @property string title + * @property string sql_title + * @property string author + * @property string sql_author + * @property string code + * @property string sql_code * @property string summary * @property string sql_summary * @property string editor @@ -26,21 +34,6 @@ function convertMSChar($src) * @property string sql_readBy * @property string cover * @property string sql_cover - * @property string typeMedia1 - * @property string sql_typeMedia1 - * - * @property string id - * @property string sql_id - * @property string title - * @property string sql_title - * @property string author - * @property string sql_author - * @property string code - * @property string sql_code - * @property string score - * @property string sql_score - * @property string type - * @property string sql_type * @property string category * @property string sql_category * @property string date @@ -59,117 +52,15 @@ function convertMSChar($src) * @property string sql_link * @property string linkTitle * @property string sql_linkTitle - * @property string itemNr - * @property string sql_itemNr + * @property string typeMedia1 + * @property string sql_typeMedia1 */ class AudioBook extends DbMapping { - public static $tableName = 'Notices'; - public static $idColumn = 'NoticeID'; - - protected $extendedAttributeNames = 'summary editor media collection isbn readBy cover typeMedia1'; - protected $attributeNames = 'id title author code score summary editor media collection isbn readBy cover type category date code3 code3Long genre genreCode coverdisplay link linkTitle itemNr typeMedia1'; - - private $loaded = false; + protected $attributeNames = 'id title author code summary editor media collection isbn readBy cover category date code3 code3Long genre genreCode coverdisplay link linkTitle typeMedia1'; - /** - * Build an AudioBook - * @param array $attributes - * @param bool $doLoadDetails - */ - public function __construct($attributes, $doLoadDetails = FALSE) - { - parent::__construct($attributes); - if ($doLoadDetails) { - $this->loadDetails(); - } - } - - public function loadDetails() - { - if ($this->loaded) { - return; - } - $this->editor = ''; - $this->summary = ''; - $this->media = ''; - $this->isbn = ''; - $this->collection = ''; - $this->category = ''; - $this->cover = ''; - - $sql_string = ''; - - // Introducing the cast as varchar(8000) to avoid the unixODBC LongText bug.. - $sql_string .= "SELECT Tag, SubfieldCode, ContentShortPart, cast(ContentLongPart as varchar(3000)) as ContentLongPart, DisplayText "; - $sql_string .= "FROM NoticeFields "; - $sql_string .= "LEFT JOIN Authorities ON Authorities.AuthorityID = NoticeFields.AuthorityID "; - $sql_string .= "WHERE NoticeID = " . $this->id . " "; - $sql_string .= "ORDER BY Tag ASC, TagRepetition ASC, SubfieldCodeNr ASC;"; - - //print $sql_string; - - // ajout de l'url de l'image amazon - - $result = Connection::execute($sql_string, true); - while ($row = $result->next()) { - - switch ($row['Tag']) { - case '520': - $this->summary = $this->addDetailToField(convertMSChar($this->summary), $row); - break; - case '260': - $this->editor = $this->addDetailToField($this->editor, $row); - break; - case '300': - $this->media = $this->addDetailToField($this->media, $row); - break; - case '020': - $this->isbn = $this->addDetailToField($this->isbn, $row); - break; - case '490': - $this->collection = $this->addDetailToField($this->collection, $row); - break; - case '600': - case '610': - case '650': - case '651': - case '655': - case '690': - case '691': - case '695': - case '696': - $this->category = $this->addDetailToField($this->category, $row); - break; - case '901': - $this->readBy = $this->addDetailToField($this->readBy, $row); - break; - case '856': - if ($row['SubfieldCode'] == 'u') { - $this->link = $this->addDetailToField($this->link, $row); - } else if ($row['SubfieldCode'] == 'z') { - $this->linkTitle = $this->addDetailToField($this->linkTitle, $row); - } - break; - case '899': - if ($row['SubfieldCode'] == 'a') { - $this->cover = "http://ecx.images-amazon.com/images/I/" . $row['ContentShortPart'] . "._SL320_.jpg"; - } - } - - if ($this->coverdisplay == 2) { - $this->cover = "http://fichiers.bibliothequesonore.ch:8089/netbiblio/images/covers/" . "Cover" . $this->id . "_Original.jpg"; - } - } - - $this->loaded = true; - } - - private function addDetailToField($actualValue, $row) - { - $actualValue = ($actualValue ? $actualValue . ' ' : ''); - $actualValue .= $row['ContentShortPart'] . $row['ContentLongPart'] . $row['DisplayText']; - return $actualValue; + public static function find($id) { + return self::findBy('NoticeID', $id); } /** @@ -178,186 +69,98 @@ class AudioBook extends DbMapping * * Beware that this search use the NoticeID, not the NoticeNr, if you need the last one * use findByCode method instead; - * @param int|array $id - * @return AudioBook|AudioBook[] - */ - public static function find($id) - { - $id = str_replace("'", "''", $id); - $fullIdColumn = 'ab.'.AudioBook::$idColumn; - if (is_array($id)) { - if (count($id) > 0) { - $condition = $fullIdColumn . ' IN (' . implode(', ', $id) . ')'; - } else { - $condition = "$fullIdColumn IS NULL"; // bad way of returning an empty ResultSet - } - $top = 'DISTINCT '; - } else { - $condition = "$fullIdColumn = $id"; - $top = 'TOP 1'; - } - - $sql = sprintf("SELECT %s - ab.[%s] AS id, - [Title] AS title, - [Author] AS author, - LTRIM(RTRIM(NoticeNr)) AS code, - RTRIM(userdefined3code) AS code3, - [code3Code].TextFre AS code3Long, - [genreCode].TextFre AS genre, - [genreCode].Code AS genreCode, - [coverdisplay], - [MediaType1Code] AS typeMedia1, - 12 AS score, - CONVERT(varchar, CreationDate, 102) AS date - FROM [%s] AS ab - INNER JOIN Codes code3Code ON ab.userdefined3code = code3Code.Code AND code3Code.Type=6 - INNER JOIN Codes genreCode ON MediaType2Code = genreCode.Code AND genreCode.Type = 2 - WHERE %s AND LTRIM(RTRIM(noticenr)) NOT LIKE '%%~%%' ORDER BY Author, Title - ;", $top, self::$idColumn, self::$tableName, $condition); - - $result_set = Connection::execute($sql, true); - - if (is_array($id)) { - $result = array(); - foreach ($id as $book_id) { - while ($row = $result_set->next()) { - if ($row['id'] == $book_id) { - $result[] = new AudioBook($row, TRUE); - break; - } - } - $result_set->rewind(); - } - } else { - $row = $result_set->next(); - if (!$row) { - return null; - // throw new Exception("NotFoundException"); - } - - $result = new AudioBook($row, TRUE); - } - - return $result; - } - - /** - * Return a book or an array of book given their notice number without any letter. - * - * if $code is an array, return an array of book. If not, return the first match. - * - * Due to the fact that notice number is incosistent in the Notices table, - * we use the si_sentences view instead. * - * @param string $code - * @return AudioBook - * @throws Exception - * @throws SqlException + * @param string $column + * @param int|array $ids + * @param bool $raw results ? + * @return AudioBook|AudioBook[]|array */ - public static function findByCode3($code) + public static function findBy($column, $ids, $raw = false) { - - $fullIdColumn = AudioBook::$tableName . '.' . AudioBook::$idColumn; - if (is_array($code)) { - - $value = str_replace("'", "''", implode(" ", $code)); - $value = str_replace(' ', "', '", $value); - $top = ''; - $condition = "si_sentences.[Key] IN ('" . $value . "')"; - } else { - - $value = str_replace("'", "''", $code); - $top = 'top 1'; - $condition = "si_sentences.[Key] = '$value'"; + $multiple = true; + if(! is_array($ids)) { + $ids = array($ids); + $multiple = false; } - $sql_string = ''; - $sql_string .= "SELECT $top $fullIdColumn as id, "; - $sql_string .= "Title as title, Author as author, si_sentences.[Key] as code, "; - $sql_string .= "Codes.TextFre As type, "; - $sql_string .= "0 AS score "; - $sql_string .= "FROM " . AudioBook::$tableName; - $sql_string .= " INNER JOIN Codes ON " . AudioBook::$tableName . ".MediaType2Code = Codes.Code AND Codes.Type = 2 "; - $sql_string .= " INNER JOIN si_sentences ON si_sentences.NoticeID = Notices.NoticeID"; - $sql_string .= " AND si_sentences.Category = 'Code'"; - $sql_string .= " WHERE ($condition) ORDER BY author, title;"; - - $result_set = Connection::execute($sql_string, false); - - if (is_array($code)) { - $result = array(); - foreach ($code as $book_code) { - while ($row = $result_set->next()) { - if ($row['code'] == $book_code) { - $result[] = new AudioBook($row, FALSE); - break; - } - } - $result_set->rewind(); + $sql = sprintf("SELECT DISTINCT + Notices.[NoticeID] AS id, + Notices.[Title] AS title, + Notices.[Author] AS author, + LTRIM(RTRIM(Notices.[NoticeNr])) AS code, + Fields.[520] AS summary, + Fields.[260b] + ' ' + Fields.[260c] AS editor, + Fields.[300] AS media, + Fields.[490a] AS collection, + isbn.DisplayText AS isbn, + Fields.[901] AS readBy, + Fields.[899a] AS cover, + '' AS category, -- supposed to come from tags 600, 610, 650, 651, 655, 690, 691, 695, 696 but always empty anyway + CONVERT(VARCHAR, Notices.[CreationDate], 102) AS date, + LTRIM(RTRIM(Notices.[userdefined3code])) AS code3, + [Code3].TextFre AS code3Long, + [GenreCode].TextFre AS genre, + [GenreCode].Code AS genreCode, + Notices.[coverdisplay], + Fields.[856u] AS link, + Fields.[856z] AS linkTitle, + Notices.[MediaType1Code] AS typeMedia1 + FROM Notices + INNER JOIN Codes AS Code3 ON Notices.userdefined3code = Code3.Code AND Code3.Type=6 + INNER JOIN Codes AS GenreCode ON MediaType2Code = GenreCode.Code AND GenreCode.Type = 2 + LEFT OUTER JOIN ( + SELECT * + FROM ( + SELECT + NoticeID, + CASE + WHEN Tag IN ('490', '260', '856', '899') THEN Tag + SubfieldCode + ELSE Tag + END AS Field, + CASE + WHEN Tag = '020' THEN CAST(AuthorityID AS varchar) + ELSE ContentShortPart + END AS Data + FROM NoticeFields + WHERE + Tag IN ( + '520', -- summary + '901', -- Reader + '300', -- Duration (field media) + '020' -- ISBN + ) + OR (Tag = '490' AND SubfieldCode = 'a') -- Collection + OR (Tag = '260' AND SubfieldCode = 'b') -- Editor + OR (Tag = '260' AND SubfieldCode = 'c') -- Edition year + OR (Tag = '856' AND SubfieldCode = 'u') -- Link + OR (Tag = '856' AND SubfieldCode = 'z') -- Link title + OR (Tag = '899' AND SubfieldCode = 'a') -- Cover + ) AS src + PIVOT ( + MIN(Data) + FOR Field IN ([520], [901], [300], [020], [490a], [260b], [260c], [856u], [856z], [899a]) + ) AS pvt + ) Fields ON Notices.NoticeID = Fields.NoticeID + LEFT JOIN Authorities AS isbn ON isbn.AuthorityID = Fields.[020] + WHERE + LTRIM(RTRIM(Notices.[%s])) IN ('%s') + AND Notices.[NoticeNr] NOT LIKE '%%~%%' + ;", $column, implode('\', \'', $ids)); + + $result = Connection::execute($sql, true); + + $books = array(); + while($row = $result->next()) { + if($row['coverdisplay'] == 2) { + $row['cover'] = 'http://fichiers.bibliothequesonore.ch:8089/netbiblio/images/covers/Cover'.$row['id'].'_Original.jpg'; + } else if(strlen($row['cover']) > 0) { + $row['cover'] = 'http://ecx.images-amazon.com/images/I/'.$row['cover'].'._SL320_.jpg'; } - } else { - $row = $result_set->next(); - if (!$row) { - throw new Exception("NotFoundException"); - } - $result = new AudioBook($row, TRUE); - } - return $result; - } - - - public static function findByCode($code) - { - - $fullIdColumn = AudioBook::$tableName . '.' . AudioBook::$idColumn; - - if (is_array($code)) { - - $value = str_replace("'", "''", implode(" ", $code)); - $value = str_replace(' ', "', '", $value); - $top = ''; - $condition = "LTRIM(RTRIM(NoticeNr)) in ('" . $value . "')"; - } else { - - $value = str_replace("'", "''", $code); - $top = 'top 1'; - $condition = "LTRIM(RTRIM(NoticeNr)) = '$value'"; + $books[] = $raw ? $row : new AudioBook($row); } - $sql_string = ''; - $sql_string .= "SELECT $top $fullIdColumn as id, "; - $sql_string .= "Notices.Title as title, Notices.Author as author, LTRIM(RTRIM(NoticeNr)) as code, "; - $sql_string .= "Codes.TextFre As type, "; - $sql_string .= "0 AS score "; - $sql_string .= "FROM " . AudioBook::$tableName; - $sql_string .= " INNER JOIN Codes ON " . AudioBook::$tableName . ".MediaType2Code = Codes.Code AND Codes.Type = 2 "; - $sql_string .= " WHERE ($condition) ORDER BY author, title ;"; - - - $result_set = Connection::execute($sql_string, false); - - if (is_array($code)) { - - $result = array(); - - while ($row = $result_set->next()) { - $result[] = new AudioBook($row, true); - - } - - return $result; - } else { - $row = $result_set->next(); - if (!$row) { - - throw new Exception("NotFoundException"); - } - $result[] = new AudioBook($row, true); - - } - return $result; + return $multiple ? $books : reset($books); } /** diff --git a/lib/BookSearch.php b/lib/BookSearch.php index 2a0a570..962b782 100644 --- a/lib/BookSearch.php +++ b/lib/BookSearch.php @@ -24,8 +24,14 @@ class BookSearch $this->client = new SolrClient($options); $this->query = new SolrQuery(); $this->query->setQuery('*:*'); + $this->query->addField('id'); + $this->query->addField('title'); + $this->query->addField('author'); $this->query->addField('code'); + $this->query->addField('category'); + $this->query->addField('summary'); + $this->query->addParam('q.op', 'AND'); } diff --git a/mobile.netbiblio.php b/mobile.netbiblio.php index 2120f1b..2bef8f0 100644 --- a/mobile.netbiblio.php +++ b/mobile.netbiblio.php @@ -230,35 +230,28 @@ class NetBiblio extends WebService public function AddWish($bookNr) { - $bookNr = intval($bookNr); - $bookId = AudioBook::findIdByCode($bookNr); - $this->data[] = $this->getUser()->addWish($bookId); + $id = AudioBook::findIdByCode(intval($bookNr)); + $this->data[] = $this->getUser()->addWish($id); } public function DeleteWish($bookNr) { - $bookNr = intval($bookNr); - $bookId = AudioBook::findIdByCode($bookNr); - $this->getUser()->deleteWish($bookId); + $id = AudioBook::findIdByCode(intval($bookNr)); + $this->getUser()->deleteWish($id); } public function FindBooks($codes) { $this->CheckSession(); - $codeList = array_map('intval', json_decode($codes, true)); - foreach ($codeList as $code) { - if ($code != 0) { - $id = AudioBook::findIdByCode($code); - $this->data[] = $this->AddFiles(AudioBook::find($id)); - } - } + $codes = json_decode($codes, true); + $codes = array_map('intval', $codes); + $books = AudioBook::findBy('NoticeNr', $codes, true); + $this->data = array_map(array($this, 'AddFiles'), $books); } - private function AddFiles(AudioBook $book) + private function AddFiles(array $book) { - $book = $book->toArray(); - $uri = sprintf("%s%s", Configuration::get('checkfile_url'), http_build_query(array( @@ -286,8 +279,8 @@ class NetBiblio extends WebService $this->CheckSession(); $code = intval($code); - $id = AudioBook::findIdByCode($code); - $this->data = $this->AddFiles(AudioBook::find($id)); + $book = AudioBook::findBy('NoticeNr', $code, true); + $this->data = $this->AddFiles($book); } public function Search($query, $start, $limit) @@ -361,7 +354,7 @@ class NetBiblio extends WebService $this->data['facets'] = $results['facet_counts']['facet_fields']; foreach ($results['response']['docs'] as $doc) { - $book = AudioBook::find($doc['id']); + $book = AudioBook::findBy('NoticeID', $doc['id'], true); if($book) { $this->data[] = $this->AddFiles($book); }