• PHP 实现简单搜索功能


    方案:问答搜索

    1. 搜索结果列表,高亮显示搜索关键词内容

    2. 用户输入内容,点击搜索
        
        2.1 获取用户的搜索内容;
        
        2.2 调用分词服务,获取对搜索内容的分词;
        
        2.3 先查询是否已经存在这些关键词内容的缓存,有则直接取结果;否,进行下一步;
        
        2.4 如果 2.2 返回的分词数大于 5 个,则取 5 个关键词的问答帖子交集,判断数量是否 >= 30 条;
            不够,则逐次丢弃最后的关键词,再次进行查询,直到关键词的个数减到只有 1 个为止;
            
            2.4.1 对 2.4 中的多次结果进行去从,以及进行帖子的权重计算
            (
                问答帖子的质量计算:
                    Q = α * T + β * S + γ * A , α = 0.2 , β = 0.5 , γ = 0.3 ;
                    T - 时间; S - 点赞数 ; A - 回答数;
                    T = (当前的时间秒戳 - 帖子的发帖时间) / 7*86400;
            )
            
        2.5 将 2.4 中的问答结果写入 Redis ,10 分钟失效;(key - hnb:qa:search_result , 帖子)
        
        2.6 读取 2.5 Redis 结果,展示到页面


    // 问答搜索 public function getQuestionBySearch($arr_keyWords , $arr_keyWeight , $start , $num) { $arr_temple_keyWords = $arr_keyWords; count($arr_keyWords) > 8 ? $len = 8 : $len = count($arr_keyWords); // redis 中的 key 值 $key = 'hnb:qa:search:qa_score:' . implode('_' , array_splice($arr_temple_keyWords , 0 , $len)); // 读取 redis 中 key = hnb-search:'关键词',... 有没有缓存. $exists = Hnb_Model_Qa_Question_Cache::getInstance()->existsKey($key); if($exists) { $arr_questionInfo = unserialize($exists); } else { $arr_questionInfo = array(); $arr_question_ids = array(); $arr_label_in_question = array(); do{ $arr_keyWords = array_splice($arr_keyWords , 0 , $len--); $arr_result = Hnb_Model_Qa_Question_Cache::getInstance()->getSearchRelativeQuestion($arr_keyWords , $start , $num); // 问答帖子 foreach($arr_result as $question) { // 去掉重复的问答 if(!in_array($question['id'] , $arr_question_ids)) { $arr_question_ids[] = $question['id']; // 权重计算 $question['score'] = pow(2 , $len); $this->_logicQaWeight($question , $arr_keyWords , $arr_keyWeight); $arr_questionInfo[] = $question; } } } while((count($arr_questionInfo) < 100) && $len); // 存在数据时 if($arr_questionInfo) { // 权重排序 //uasort($arr_questionInfo , array($this , 'cmp')); usort($arr_questionInfo , array($this , 'cmp')); // 保存临时数据 //Hnb_Model_Qa_Question_Cache::getInstance()->saveTempleData($key , $arr_questionInfo , $timeOutSecond = 600); // 设定该临时数据的失效时间 } } return $arr_questionInfo; } // 按帖子的权重排序 private function cmp($a , $b) { if($a['score'] == $b['score']) { return 0; } return ($a['score'] > $b['score']) ? -1 : 1; } // 问答帖子的权重计算逻辑 private function _logicQaWeight(&$questionInfo , $arr_keyWords , $arr_keyWeight) { $a = 0.2; // 发帖时间 $b = 0.5; // 点赞数 $c = 0.3; // 回复数 //$d = ..; // 匹配度因子 $b = $c = 0; $timeLine = 30 * 86400; // $minus = time() - $questionInfo['create_time']; // 向下取整 $t = floor($minus / $timeLine); $tParam = 2 * pow(0.5 , $t); // 用户回答 $user_answers = Hnb_Model_Qa_Answer::getInstance()->getAnswerInfoByQuestion($questionInfo['id']); // 顾问回答权重计算 if($user_answers) { is_string($user_answers) ? $user_answers = unserialize($user_answers) : ''; $praise_num = null; foreach($user_answers as $answer) { $praise_num += $answer['praise_num']; } } else { $praise_num = 0; } // 匹配度因子计算 $this->_matchingQARate($questionInfo , $arr_keyWords , $arr_keyWeight); $weight = $a * $tParam + $b * $praise_num + $c * $questionInfo['answer_num']; $questionInfo['all_praise_num'] = $praise_num; $questionInfo['keywords'] = implode(',' , $arr_keyWords); $questionInfo['params'] = '时间-' . ($a * $tParam) . '##tParam-' . $tParam. '## 点赞数-' . ($b * $praise_num) . '## 回复数-' . ($c * $questionInfo['answer_num']); $questionInfo['score'] = $questionInfo['score'] + $weight; //print_r($questionInfo); } // 帖子的匹配度 public function _matchingQARate(&$questionInfo , $arr_keyWords , $arr_keyWeight) { // 1. 发送搜索内容到分词服务 $arr_kwIntersect_result = array_intersect($arr_keyWords , $questionInfo['keyword']); echo '交集'; print_r($arr_kwIntersect_result); // 2. 获取到返回的分词与权重 $arr_format_wordInfo = Hnb_Model_Search::getInstance()->formatWordInfo($questionInfo['keyword2']); // 帖子关键词的权重,注意次序 $w = array(); foreach($arr_format_wordInfo as $wordInfo) { if(in_array($wordInfo['keyword'] , $arr_kwIntersect_result)) { $w[] = $wordInfo['weight']; } } // 搜索内容分词的权重,注意次序 $y = array(); foreach($arr_keyWeight as $weightInfo) { if(in_array($weightInfo['keyword'] , $arr_kwIntersect_result)) { $y[] = $weightInfo['weight']; } } print_r($w); echo '<br />'; print_r($y); echo '###############'; $element = null; foreach($w as $key => $v) { $element += $v * $y[$key]; } echo $element; // 3. 与搜索出来的帖子做交集 // 4. 计算帖子的匹配度 /* * 计算公式: * 3 中的交集作为分子 * 3 中的帖子与 2 的分词权重 */ }
  • 相关阅读:
    Node Sass version 5.0.0 is incompatible with^4.0.0
    Vue v-html 的使用
    SQL 判断时间是否为空
    Element UI 表单验证
    Mybatis-Plus根据条件更新
    语法检查工具 http://jshint.com/
    安装node_modules文件遇到的问题:更改代理
    知识点3: 学习中遇到的问题
    Vue: 用 key 管理可复用的元素
    Vue遇到的问题
  • 原文地址:https://www.cnblogs.com/shuman/p/4789567.html
Copyright © 2020-2023  润新知