搜索 version

环境配置

MySQL 5.6前,只有 MyISAM 引擎支持全文搜索,MySQL 5.6 InnoDB 也支持全文索引。

配置mysql.cnf

  1. #mysql指定了最小字符长度,默认是4,必须要匹配大于4的才会有返回结果
  2. ft_min_word_len = 2

字段是否加入全文搜索

图片

搜索页面入口?

  1. http://you_domain.com/index.php?g=Search

如何主动更新索引?

更新索引,更新需要检索字段的分词

  1. $SearModel::search_api($id, $data, $modelid);
  2. # data 为传入该行数据 ,由$modelid + $id 两条件筛选出来

如何根据输入的关键字获取索引结果?

思路:先把关键字分词,然后进行检索。

核心代码

  1. //分词结果
  2. if ($this->config['dzsegment']) {
  3. //用discuz的分词接口,http调用,比较耗时
  4. $segment_q = D('Search/Search')->discuzSegment($q);
  5. } else {
  6. //内置的分词方法
  7. $segment_q = D('Search/Search')->segment($q);
  8. }
  9. if (!empty($segment_q[0]) && $this->config['segment']) {
  10. $words = $segment_q;
  11. $segment_q = implode(' ', $segment_q);
  12. $where['_string'] = " MATCH (`data`) AGAINST ('{$segment_q}' IN BOOLEAN MODE) ";
  13. } else {
  14. //不推荐,性能差。若分词失败什么的,用最暴力的模糊查询
  15. $likeList = explode(' ', $q);
  16. if (count($likeList) > 1) {
  17. foreach ($likeList as $k => $rs) {
  18. $likeList[$k] = "%{$rs}%";
  19. }
  20. $where['data'] = array('like', $likeList, 'or');
  21. } else {
  22. $where['data'] = array('like', "%{$q}%");
  23. }
  24. $words = array($q);
  25. }
  26. //查询结果缓存
  27. if ($cachetime) {
  28. //统计
  29. $count = M('Search')->where($where)->cache(true, $cachetime)->count();
  30. $page = page($count, $pagesize);
  31. $result = M('Search')->where($where)->cache(true, $cachetime)->limit($page->firstRow . ',' . $page->listRows)->order($order)->select();
  32. } else {
  33. $count = M('Search')->where($where)->count();
  34. $page = page($count, $pagesize);
  35. $result = M('Search')->where($where)->limit($page->firstRow . ',' . $page->listRows)->order($order)->select();
  36. }