何为搜索及时响应
就是根据用户在搜索框输入的内容,即使展示出用户有可能要搜索的东西,带来良好的用户体验!
本文展示的是用ES如何实现类似功能 !
索引创建
$query = array(
'settings'=>array(
'index'=>array(
'max_result_window'=>1000000,
),
'analysis'=>array(
'filter'=>array(
'edge_ngram_filter'=>array(
'type'=>'edge_ngram',//中华人名共和国 会分成:中、中华、中华人、中华人民等
'min_gram'=>1,//分词之后每个词的最小长度
'max_gram'=>30//分词之后每个词的最大长度
),
'pinyin_edge_ngram_filter'=>array(
'type'=>'edge_ngram',//中华人名共和国 会分成:中、中华、中华人、中华人民等
'min_gram'=>1,//分词之后每个词的最小长度
'max_gram'=>180//分词之后每个词的最大长度
),
'pinyin_full_filter'=>array(
'keep_first_letter'=>false,
'type'=>'pinyin',
'keep_original'=>false,// 当启用此选项时,也会保留原始输入,默认值:false
'keep_full_pinyin'=>false,//当启用该选项,例如:刘德华> [ liu,de,hua],默认值:true
'keep_joined_full_pinyin'=>true,//当启用此选项时,例如:刘德华> [ liudehua],默认值:false
),
'all_pinyin_filter'=>array(//首字母,全拼分词
'keep_first_letter'=>true,//keep_first_letter启用此选项时,例如:刘德华> ldh,默认值:true
'keep_separate_first_letter'=>false,//启用该选项时,将保留第一个字母分开,例如:刘德华> l,d,h,默认:假的,注意:查询结果也许是太模糊,由于长期过频
'keep_none_chinese_in_first_letter'=>true,//第一个字母保持非中文字母,例如:刘德华AT2016- > ldhat2016,默认值:true
'type'=>'pinyin',
'keep_original'=>false,// 当启用此选项时,也会保留原始输入,默认值:false
'limit_first_letter_length'=>10,//设置first_letter结果的最大长度,默认值:16
'lowercase'=>true,//小写非中文字母,默认值:true
'keep_full_pinyin'=>false,//当启用该选项,例如:刘德华> [ liu,de,hua],默认值:true
'keep_joined_full_pinyin'=>true,//当启用此选项时,例如:刘德华> [ liudehua],默认值:false
)
),
'analyzer'=>array(
'prefixIndexAnalyzer'=>array(//索引时使用分词策略:前缀分词 如:中华人民共和国,分城:中、中华、中华人、中华人民等
'type'=>'custom',
'tokenizer'=>'keyword',
'filter'=>array('edge_ngram_filter')
),
'prefixSearchAnalyzer'=>array(//搜索时使用分词策略:指定搜索时走的分词策略,该分词策略不分词
'type'=>'keyword'
),
'pinyinPrefixIndex'=>array(//索引时使用分词策略:拼音 全拼、首字母 前缀分词 如:双眼,分城:首字母的:s、sy;全拼的:s、sh、shu、shua、shuan、shuang、shuangy等
'type'=>'custom',
'tokenizer'=>'keyword',
'filter'=>array('all_pinyin_filter','pinyin_edge_ngram_filter')
),
'pinyinPrefixSearch'=>array(//搜索时使用分词策略:指定搜索时走的分词策略,该分词策略不分词,原词搜索
'type'=>'custom',
'tokenizer'=>'keyword',
),
'pinyinStandardIndex'=>array(//索引时使用分词策略:拼音全拼 最精细拆分 如:双眼,分成:s、sh、shu等
'type'=>'custom',
'tokenizer'=>'standard',
'filter'=>array('pinyin_full_filter','edge_ngram_filter')//先拆成一个个的全拼,接着再对每一个拼音做前缀分;如 双眼,首先拆分成shuang跟yan,接着再拆,拆成:s、sh、shu、shua、shuan、shuang
),
'pinyinStandardSearch'=>array(//搜索时使用分词策略:将输入词按照拼音拆,不管输入的是全字母还是混合还是全中文
'type'=>'custom',
'tokenizer'=>'standard',
'filter'=>array('pinyin_full_filter')
)
)
)
),
'mappings'=>array(
$this->type=>array(
'_all'=>array('enabled'=>false),
'dynamic'=>false,
'properties'=>array(
'data_type'=>array('type'=>'byte'),//数据类型 1:根据搜索日志洗出来SUG词 2:医生 3:医院 4 标签 5 系统手动设置的词 6:热词推荐
'data_id'=>array('type'=>'integer'),//数据类型对应的ID 2:医生(medical_doctors.id) 3:医院(medical_agencies.id) 4 标签(medical_bbs_board.id)
'date'=>array('type'=>'integer'),//数据所属时间范围,格式:20190320;
'pv'=>array('type'=>'integer'),//PV
'uv'=>array('type'=>'integer'),//UV
'city_id'=>array('type'=>'integer'),//特定城市下的数据
"city_type"=>array('type'=>'byte'),//城市类型:1:区域城市(medical_area_operate),city_name:区域ID(medical_area_operate->ID)
'to_skudetail_pv'=>array('type'=>'integer'),//进入SKU详情页的PV
'to_skudetail_uv'=>array('type'=>'integer'),//进入SKU详情页的UV
'search_word'=>array(
'type'=>'keyword',
'index'=>'not_analyzed',
'fields'=>array(
'prefix_word'=>array(//中文前缀匹配
'analyzer'=>'prefixIndexAnalyzer',//索引时指定的分析器
'type'=>'text',
'search_analyzer'=>'prefixSearchAnalyzer',//搜索时指定的分析器
'position_increment_gap'=>100,//当我们去索引一个含有多个值的 text 字段时,会在各个值之间添加一个假想的空间,将值隔开,这样就可以有效避免一些无意义的短语匹配,间隙大小通过 position_increment_gap 来控制,默认是 100
),
'ik_word'=>array(
'analyzer'=>'standard',
'type'=>'text',
'search_analyzer'=>'standard',
'position_increment_gap'=>100,
),
'prefix_pinyin'=>array(//全拼,首字母前缀匹配
'analyzer'=>'pinyinPrefixIndex',
'type'=>'text',
'search_analyzer'=>'pinyinPrefixSearch',
'position_increment_gap'=>100,
),
'standard_pinyin'=>array(//全拼,首字母完全匹配
'analyzer'=>'pinyinStandardIndex',
'type'=>'text',
'search_analyzer'=>'pinyinStandardSearch',
'position_increment_gap'=>100,
),
)
),//搜索词
'unique_md5' => array('type'=>'keyword','index'=>'not_analyzed'),//保证不出现重复数据
'hit_type'=>array('type'=>'byte'),//搜索词命中类型 1:二级项目 2:三级项目 3:扩展标签(适应症、功效次) 4:医生 5:医院
'show_word_length'=>array('type'=>'integer'),//展示词长度
'show_word'=>array('type'=>'keyword'),//展示词
'weight_num'=>array('type'=>'integer'),//系统手动设置的权重 整数为置顶 负数为置底 降序
'sug_type'=>array('type'=>'byte'),//medical_suggest_artificial->sug_type
'status'=>array('type'=>'byte'),//2:正常 1:删除
)
)
)
);
查询:
$multiMatch_fields=array('search_word.ik_word','search_word.prefix_word^50');//SUG词,优先展示前缀匹配的
$multiMatch_type='phrase';//短语匹配-》顺序不能乱,比如库里是割双眼皮 搜双眼皮割不能搜出来
if(preg_match('/^[A-Za-z]+$/',$searchWd)){//全拼音
$multiMatch_fields=array('search_word.standard_pinyin','search_word.prefix_pinyin^50');
}elseif(preg_match('/[A-Za-z]+/',$searchWd)){//有字母
$multiMatch_fields=array('search_word.ik_word^70','search_word.prefix_word^10','search_word.standard_pinyin','search_word.prefix_pinyin^50');
}
$query_must=array(
array(
'multi_match' => array(
'query'=>$searchWd,
'fields'=>$multiMatch_fields,
'minimum_should_match'=>'100%',
'type'=>$multiMatch_type
)
)
);