CodeIgniter中Select2 Ajax搜索的模糊匹配优化方案问询
实现Select2 Ajax模糊匹配(支持标点、空格、连写关键词)
要实现不同格式关键词的统一匹配,我们需要在客户端预处理搜索词,同时在服务端(CodeIgniter)对数据库字段做相同规则的标准化处理,最终通过模糊匹配实现需求。
一、客户端代码修改
在原Select2代码中添加搜索词预处理函数,将用户输入的标点、空格全部移除并转为小写,确保不同格式的输入生成统一的搜索串:
// 标准化搜索词:移除非字母数字字符并转小写 function normalizeSearchTerm(term) { return term.toLowerCase().replace(/[^a-z0-9]/g, ''); } $('.search_equipment').each(function(){ var elemX = $(this); if (elemX.data('mode')=="ajax"){ elemX.select2({ ajax: { url: '{site_url}inventory/', dataType: 'json', delay: 250, data: function (params) { var xRet = { q: normalizeSearchTerm(params.term), // 传入预处理后的搜索词 page: params.page, atype: elemX.data("t"), }; if (elemX.data('connected_to')){ xRet['parent_ids'] = jQuery(elemX.data('connected_to')).val(); } return xRet; }, processResults: function (data, params) { params.page = params.page || 1; return { results: data.items, pagination: { more: (params.page * 30) < data.total_count } }; }, cache: false }, placeholder: 'Search for ' + elemX.data('text'), escapeMarkup: function (markup) { return markup; }, minimumInputLength: 1 }); }else{ elemX.select2({ placeholder: "Select a " + elemX.data('text') }); } });
二、CodeIgniter服务端处理
在inventory控制器的对应方法中,接收预处理后的搜索词,对数据库中的设备名称执行相同规则的标准化,再进行模糊匹配。
方案1:兼容MySQL 8.0+(支持REGEXP_REPLACE)
public function index() { $q = $this->input->get('q'); $atype = $this->input->get('atype'); $parent_ids = $this->input->get('parent_ids'); $page = $this->input->get('page', 1); $per_page = 30; $offset = ($page - 1) * $per_page; // 标准化搜索词(和客户端规则一致) $normalized_q = strtolower(preg_replace('/[^a-z0-9]/', '', $q)); $like_term = "%{$normalized_q}%"; // 查询数据 $this->db->select('id, name as text'); $this->db->from('equipment'); if ($atype) { $this->db->where('type', $atype); } if ($parent_ids) { $this->db->where_in('parent_id', explode(',', $parent_ids)); } // 对设备名称标准化后模糊匹配 $this->db->where("LOWER(REGEXP_REPLACE(name, '[^a-zA-Z0-9]', '')) LIKE ?", $like_term); $this->db->limit($per_page, $offset); $items = $this->db->get()->result_array(); // 获取总条数(需重新构建查询) $this->db->reset_query(); $this->db->from('equipment'); if ($atype) $this->db->where('type', $atype); if ($parent_ids) $this->db->where_in('parent_id', explode(',', $parent_ids)); $this->db->where("LOWER(REGEXP_REPLACE(name, '[^a-zA-Z0-9]', '')) LIKE ?", $like_term); $total_count = $this->db->count_all_results(); echo json_encode([ 'items' => $items, 'total_count' => $total_count ]); }
方案2:兼容低版本MySQL(无REGEXP_REPLACE)
手动替换常见标点符号:
// 替换设备名称中的标点、空格 $this->db->where("LOWER(REPLACE(REPLACE(REPLACE(name, '.', ''), '-', ''), ' ', '')) LIKE ?", $like_term);
效果说明
- 用户输入
e.c.g/E C G/ecg都会被处理成ecg,服务端将E.C.G Machine标准化为ecgmachine,通过LIKE '%ecg%'匹配到结果。 - 用户输入
x-ray/xray/x ray都会被处理成xray,服务端将X-Ray Machine标准化为xraymachine,实现精准匹配。
内容的提问来源于stack exchange,提问作者Muhammad Asif Raza
相关产品推荐
相关产品推荐

