static function getSuggestions($userId = -1) { global $configArray; if ($userId == -1) { global $user; $userId = $user->id; } //Load all titles the user is not interested in $notInterestedTitles = array(); $notInterested = new NotInterested(); $resource = new Resource(); $notInterested->joinAdd($resource); $notInterested->userId = $userId; $notInterested->find(); while ($notInterested->fetch()) { if ($notInterested->source == 'VuFind') { $fullId = $notInterested->record_id; } else { $fullId = 'econtentRecord' . $notInterested->record_id; } $notInterestedTitles[$fullId] = $fullId; } //Load all titles the user has rated (print) $allRatedTitles = array(); $allLikedRatedTitles = array(); $ratings = new UserRating(); $ratings->userid = $userId; $resource = new Resource(); $notInterested->joinAdd($resource); $ratings->joinAdd($resource); $ratings->find(); while ($ratings->fetch()) { $allRatedTitles[$ratings->record_id] = $ratings->record_id; if ($ratings->rating >= 4) { $allLikedRatedTitles[] = $ratings->record_id; } } //Load all titles the user has rated (eContent) $econtentRatings = new EContentRating(); $econtentRatings->userId = $userId; $econtentRatings->find(); while ($econtentRatings->fetch()) { $allRatedTitles['econtentRecord' . $econtentRatings->recordId] = 'econtentRecord' . $econtentRatings->recordId; if ($econtentRatings->rating >= 4) { $allLikedRatedTitles[] = 'econtentRecord' . $econtentRatings->recordId; } } // Setup Search Engine Connection $class = $configArray['Index']['engine']; $url = $configArray['Index']['url']; $db = new $class($url); if ($configArray['System']['debugSolr']) { $db->debug = true; } //Get a list of all titles the user has rated (3 star and above) $ratings = new UserRating(); $ratings->whereAdd("userId = {$userId}", 'AND'); $ratings->whereAdd('rating >= 3', 'AND'); $ratings->orderBy('rating DESC, dateRated DESC, id DESC'); //Use the 20 highest ratings to make real-time recommendations faster $ratings->limit(0, 5); $ratings->find(); $suggestions = array(); //echo("User has rated {$ratings->N} titles<br/>"); if ($ratings->N > 0) { while ($ratings->fetch()) { $resourceId = $ratings->resourceid; //Load the resource $resource = new Resource(); $resource->id = $resourceId; $resource->find(); if ($resource->N != 1) { //echo("Did not find resource for $resourceId<br/>"); } else { $resource->fetch(); //echo("Found resource for $resourceId - {$resource->title}<br/>"); $ratedTitles[$resource->record_id] = clone $ratings; $numRecommendations = 0; if ($resource->isbn) { //If there is an isbn for the title, we can load similar titles based on Novelist. $isbn = $resource->isbn; $numRecommendations = Suggestions::getNovelistRecommendations($ratings, $isbn, $resource, $allRatedTitles, $suggestions, $notInterestedTitles); //echo(" - Found $numRecommendations for $isbn from Novelist<br/>"); } if ($numRecommendations == 0) { Suggestions::getSimilarlyRatedTitles($db, $ratings, $userId, $allRatedTitles, $suggestions, $notInterestedTitles); //echo(" - Found $numRecommendations based on ratings from other users<br/>"); } } } } //Also get eContent the user has rated highly $econtentRatings = new EContentRating(); $econtentRatings->userId = $userId; $econtentRatings->whereAdd('rating >= 3'); $econtentRatings->orderBy('rating DESC, dateRated DESC'); $econtentRatings->limit(0, 5); $econtentRatings->find(); //echo("User has rated {$econtentRatings->N} econtent titles<br/>"); if ($econtentRatings->N > 0) { while ($econtentRatings->fetch()) { //echo("Processing eContent Rating {$econtentRatings->recordId}<br/>"); //Load the resource $resource = new Resource(); $resource->record_id = $econtentRatings->recordId; $resource->source = 'eContent'; $resource->find(); if ($resource->N != 1) { //echo("Did not find resource for $resourceId<br/>"); } else { $resource->fetch(); //echo("Found resource for $resourceId - {$resource->title}<br/>"); $ratedTitles[$resource->record_id] = clone $econtentRatings; $numRecommendations = 0; if ($resource->isbn) { //If there is an isbn for the title, we can load similar titles based on Novelist. $isbn = $resource->isbn; $numRecommendations = Suggestions::getNovelistRecommendations($ratings, $isbn, $resource, $allRatedTitles, $suggestions, $notInterestedTitles); //echo(" - Found $numRecommendations for $isbn from Novelist<br/>"); } if ($numRecommendations == 0) { Suggestions::getSimilarlyRatedTitles($db, $ratings, $userId, $allRatedTitles, $suggestions, $notInterestedTitles); //echo(" - Found $numRecommendations based on ratings from other users<br/>"); } } } } $groupedTitles = array(); foreach ($suggestions as $suggestion) { $groupingTerm = $suggestion['titleInfo']['grouping_term']; $groupedTitles[] = $groupingTerm; } //If the user has not rated anything, return nothing. if (count($allLikedRatedTitles) == 0) { return array(); } //Get recommendations based on everything I've rated using more like this functionality $class = $configArray['Index']['engine']; $url = $configArray['Index']['url']; /** @var Solr $db */ $db = new $class($url); //$db->debug = true; $moreLikeTheseSuggestions = $db->getMoreLikeThese($allLikedRatedTitles); //print_r($moreLikeTheseSuggestions); if (count($suggestions) < 30) { foreach ($moreLikeTheseSuggestions['response']['docs'] as $suggestion) { $groupingTerm = $suggestion['grouping_term']; if (array_key_exists($groupingTerm, $groupedTitles)) { //echo ($suggestion['grouping_term'] . " is already in the suggestions"); continue; } $groupedTitles[$groupingTerm] = $groupingTerm; //print_r($suggestion); if (!array_key_exists($suggestion['id'], $allRatedTitles) && !array_key_exists($suggestion['id'], $notInterestedTitles)) { $suggestions[$suggestion['id']] = array('rating' => $suggestion['rating'] - 2.5, 'titleInfo' => $suggestion, 'basedOn' => 'MetaData for all titles rated'); } if (count($suggestions) == 30) { break; } } } //print_r($groupedTitles); //sort suggestions based on score from ascending to descending uasort($suggestions, 'Suggestions::compareSuggestions'); //Only return up to 50 suggestions to make the page size reasonable $suggestions = array_slice($suggestions, 0, 30, true); //Return suggestions for use in the user interface. return $suggestions; }