VodSearch.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. namespace app\common\model;
  3. use think\Db;
  4. use think\Cache;
  5. class VodSearch extends Base {
  6. // 设置数据表(不含前缀)
  7. protected $name = 'vod_search';
  8. // 最大Id数量,使用IN查询时,超过一定数量,查询不使用索引了
  9. public $maxIdCount = 1000;
  10. private $updateTopCount = 50000;
  11. /**
  12. * 获取结果Id列表
  13. */
  14. public function getResultIdList($search_word, $search_field, $word_multiple = false)
  15. {
  16. $search_word = trim($search_word);
  17. $search_word = str_replace(',,', '', $search_word);
  18. if (strlen($search_word) == 0 || strlen($search_field) == 0) {
  19. return [];
  20. }
  21. // 如果包含多个关键词,使用递归处理
  22. if ($word_multiple === true) {
  23. $id_list = [];
  24. $search_word_exploded = explode(',', $search_word);
  25. foreach ($search_word_exploded as $search_word) {
  26. $id_list += $this->getResultIdList($search_word, $search_field);
  27. }
  28. $id_list = array_unique($id_list);
  29. return $id_list;
  30. }
  31. $search_key = md5($search_word . '@' . $search_field);
  32. $where = ['search_key' => $search_key];
  33. $search_row = $this->where($where)->field("search_result_ids, search_hit_count")->find();
  34. if (empty($search_row)) {
  35. $where_vod = [];
  36. $where_vod[$search_field] = ['LIKE', '%' . $search_word . '%'];
  37. $id_list = Db::name('Vod')->where($where_vod)->order("vod_id ASC")->column("vod_id");
  38. $id_list = is_array($id_list) ? $id_list : [];
  39. $this->insert([
  40. 'search_key' => $search_key,
  41. 'search_word' => mb_substr($search_word, 0, 128),
  42. 'search_field' => mb_substr($search_field, 0, 64),
  43. 'search_hit_count' => 1,
  44. 'search_last_hit_time' => time(),
  45. 'search_update_time' => time(),
  46. 'search_result_count' => count($id_list),
  47. 'search_result_ids' => join(',', $id_list),
  48. ]);
  49. } else {
  50. $id_list = explode(',', (string)$search_row['search_result_ids']);
  51. $id_list = array_filter($id_list);
  52. $this->where($where)->update([
  53. 'search_hit_count' => $search_row['search_hit_count'] + 1,
  54. 'search_last_hit_time' => time(),
  55. ]);
  56. }
  57. $id_list = array_map('intval', $id_list);
  58. $id_list = empty($id_list) ? [0] : $id_list;
  59. return $id_list;
  60. }
  61. /**
  62. * 前端是否开启
  63. */
  64. public function isFrontendEnabled()
  65. {
  66. $config = config('maccms');
  67. // 未设置时,默认关闭
  68. if (!isset($config['app']['vod_search_optimise'])) {
  69. return false;
  70. }
  71. $list = explode('|', $config['app']['vod_search_optimise']);
  72. return in_array('frontend', $list);
  73. }
  74. /**
  75. * 采集是否开启
  76. */
  77. public function isCollectEnabled()
  78. {
  79. $config = config('maccms');
  80. // 未设置时,默认关闭
  81. if (!isset($config['app']['vod_search_optimise'])) {
  82. return false;
  83. }
  84. $list = explode('|', $config['app']['vod_search_optimise']);
  85. return in_array('collect', $list);
  86. }
  87. /**
  88. * 检查更新搜索结果
  89. */
  90. public function checkAndUpdateTopResults($vod, $force = false)
  91. {
  92. static $list;
  93. if (empty($vod['vod_id'])) {
  94. return;
  95. }
  96. if (is_null($list)) {
  97. $cach_name = 'vod_search_top_result_v2_' . $this->updateTopCount;
  98. $list = $force ? [] : Cache::get($cach_name);
  99. if (empty($list)) {
  100. $list = $this->field("search_key, search_word, search_field")->order("search_hit_count DESC, search_last_hit_time DESC")->limit("0," . $this->updateTopCount)->select();
  101. $force === false && Cache::set($cach_name, $list, count($list) < ($this->updateTopCount / 10) ? 3600 : 86400);
  102. $this->clearOldResult();
  103. }
  104. }
  105. $time_now = time();
  106. foreach ($list as $row) {
  107. foreach (explode('|', $row['search_field']) as $field) {
  108. if (!isset($vod[$field]) || strlen($vod[$field]) == 0) {
  109. continue;
  110. }
  111. if (stripos($vod[$field], $row['search_word']) === false) {
  112. continue;
  113. }
  114. Db::execute("UPDATE `" . config('database.prefix') . $this->name . "` SET
  115. search_update_time='{$time_now}',
  116. search_result_count=search_result_count+1,
  117. search_result_ids=CONCAT(search_result_ids,',','{$vod['vod_id']}')
  118. WHERE search_key='{$row['search_key']}'");
  119. }
  120. }
  121. }
  122. /**
  123. * 获取结果缓存的分钟数,后台配置覆盖默认值
  124. */
  125. public function getResultCacheMinutes($config = []) {
  126. // 默认14天
  127. $minutes = 20160;
  128. $config = $config ?: config('maccms');
  129. if (isset($config['app']['vod_search_optimise_cache_minutes']) && (int)$config['app']['vod_search_optimise_cache_minutes'] > 0) {
  130. $minutes = (int)$config['app']['vod_search_optimise_cache_minutes'];
  131. }
  132. return $minutes;
  133. }
  134. /**
  135. * 清理老的数据
  136. */
  137. public function clearOldResult($force = false)
  138. {
  139. // 清理多久前的
  140. $clear_seconds = $this->getResultCacheMinutes() * 60;
  141. // 设置间隔,每天最多清理1次
  142. $cach_name = 'interval_vs_clear_old_v1_' . $clear_seconds;
  143. $cache_data = Cache::get($cach_name);
  144. if ($force === false && !empty($cache_data)) {
  145. return;
  146. }
  147. Cache::set($cach_name, 1, min($clear_seconds, 86400));
  148. // vod_actor在采集的时候可提高效率,暂不清理
  149. $where = [
  150. 'search_field' => ['neq', 'vod_actor'],
  151. 'search_update_time' => ['lt', time() - $clear_seconds],
  152. ];
  153. // 后台强制清理时,都清掉
  154. if ($force === true) {
  155. unset($where['search_field']);
  156. }
  157. $this->where($where)->delete();
  158. }
  159. }