Elasticsearch实现类似 like '?%' 搜索
在做搜索的时候,下拉联想词的搜索肯定是最常见的一个场景,用户在输入的时候,要自动补全词干,说得简单点,就是以...开头搜索,如果是数据库,一句SQL就很容易实现,但在elasticsearch如何实现呢?
大家可能会立马想到用elasticsearch自带的suggest功能,确实,在一些初级应用场景,特别是数据量比较少的情况下,suggest可以快速简易的解决问题。
在数据量比较大的时候,性能有待提高,而且遇到复杂场景,suggest就会显得力不从心,看下面一个需求:
1、下拉结果需要根据城市过滤
2、下拉结果需要根据拼音搜索、首字母搜索、中文拼音混合搜索等
如果使用suggest,是不是无从下手?
下面我介绍另外二种实现的方式,这二种试更加灵活,以上二个问题皆可解决,由于篇幅,我将在其他章节具体讲解拼音+混合搜索。
一、基于正则表达式搜索
要点:索引的时候,使用"keyword"作为tokenizer,把整个文本当作一个term。
curl -XPUT localhost:9200/search_words_index -d '{
"settings" : {
"refresh_interval" : "5s",
"number_of_shards" : 1,
"number_of_replicas" : 1,
"analysis" : {
"analyzer": {
"myAnalyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": ["lowercase"]
}
}
}
},
"mappings": {
"search_words_type": {
"properties": {
"words": {
"type": "string",
"index": "analyzed",
"indexAnalyzer" : "myAnalyzer"
}
}
}
}
}
}'
搜索的时候,可使用queryStringQuery或者wildcardQuery实现正则表达式查询,啰嗦一句,queryStringQuery与wildcardQuery的区别是,wildcardQuery是一种低级查询,不会进行analyzer的,而queryStringQuery则会,更具体区别的可参考官网资料。
下面以queryStringQuery方式为例进行说明,关键代码:
String reg=/key.*/;
QueryBuilders.queryStringQuery(reg).field("words").analyzer("myAnalyzer"));
这种方式的优点是简单,索引空间占用也不大,效率也还可以,但我更推荐下面的一种式,性能会更佳。
二、基于edge-ngram分词法
这种方式是典型的以空间换时间的做法,唯一的缺点是会加大索引开销,索引数据的时间也会加长,但这种开销都是在索引阶段,并不会影响查询阶段,只要有足够的磁盘和内存空间,效率还是很不错的。
要点:索引阶段使用edge-ngram分词,按金字塔式的分割成独立的term。如下:
中华人民共和国
中华人民共和
中华人民共
中华人民
中华人
中华
中
索引如下:
curl -XPUT localhost:9200/search_words_index -d '{
"settings" : {
"refresh_interval" : "5s",
"number_of_shards" : 1,
"number_of_replicas" : 1,
"analysis" : {
"filter": {
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 30
},
"analyzer": {
"myAnalyzer": {
"type": "custom",
"tokenizer": "keyword",
"filter": ["edge_ngram_filter","lowercase"]
}
}
}
},
"mappings": {
"search_words_type": {
"properties": {
"words": {
"type": "string",
"index": "analyzed",
"indexAnalyzer" : "myAnalyzer"
}
}
}
}
}
}'
搜索的时候,直接使用term查询,如果比较复杂的情况下,如要按拼音、中文繁体转换等,则使用matchQuery,先对关键字进行一次分析。
QueryBuilders.termQuery("words", key);//低级查询,速度快
或者
QueryBuilders.matchQuery("words", key).analyzer("xxx");//可指定分词器来分析关键字
这种搜索结果保证一定是以..开头,因为在索引阶段就已经把term限定了。
注意:以上java代码示例都是基于spring-data-elasticsearch框架。
Elasticsearch实现类似 like '?%' 搜索的更多相关文章
- 转:在ElasticSearch之下(图解搜索的故事)
ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事) 摘要 先自上而下,后自底向上的介绍ElasticSearch的底层工作原理,试图回答以下问题: 为什么我 ...
- Elasticsearch java api 基本搜索部分详解
文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...
- ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事)
ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事) 摘要 先自上而下,后自底向上的介绍ElasticSearch的底层工作原理,试图回答以下问题: 为什么我 ...
- ElasticSearch 2 (18) - 深入搜索系列之控制相关度
ElasticSearch 2 (18) - 深入搜索系列之控制相关度 摘要 处理结构化数据(比如:时间.数字.字符串.枚举)的数据库只需要检查一个文档(或行,在关系数据库)是否与查询匹配. 布尔是/ ...
- ElasticSearch 2 (17) - 深入搜索系列之部分匹配
ElasticSearch 2 (17) - 深入搜索系列之部分匹配 摘要 到目前为止,我们介绍的所有查询都是基于完整术语的,为了匹配,最小的单元为单个术语,我们只能查找反向索引中存在的术语. 但是, ...
- ElasticSearch 2 (16) - 深入搜索系列之近似度匹配
ElasticSearch 2 (16) - 深入搜索系列之近似度匹配 摘要 标准的全文搜索使用TF/IDF处理文档.文档里的每个字段或一袋子词.match 查询可以告诉我们哪个袋子里面包含我们搜索的 ...
- ElasticSearch 2 (15) - 深入搜索系列之多字段搜索
ElasticSearch 2 (15) - 深入搜索系列之多字段搜索 摘要 查询很少是简单的一句话匹配(one-clause match)查询.很多时候,我们需要用相同或不同的字符串查询1个或多个字 ...
- ElasticSearch 2 (13) - 深入搜索系列之结构化搜索
ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ...
- Ajax以及类似百度搜索框的demo
public class Ajax01 extends HttpServlet{ @Override protected void service(HttpServletRequest request ...
随机推荐
- ER图是啥?
文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型.属性和联系的方法,用来描述现 ...
- html表单 2017-03-10PM
在写表单之前补充一点:网页名以及属性的值命名都不能用中文,尽量用英文或拼音. html表单特写 1.表单格式 <form method="get/post" action=& ...
- struts2学习笔记 ⑤
拦截器初探 昨天临睡觉之前看了看拦截器,也在昨天的学习笔记里面胡诌诌了几句,今天就来好好的会会拦截器这个东西.实际上拦截器是一种模块实现的机制<起码我是这么体会的>(至于说书里面说体现了A ...
- yii2的变量是如何注入到视图中去的?
我对yii2的控制器中的变量如何渲染到视图中这个问题一直很好奇,另外,我还对yii2如何加载静态资源,如js和css比较好奇,于是趁着周末就看了下yii2的相关源码想把这两个问题都弄明白.变量如何渲染 ...
- UITextField输入限制/小数/首位等
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementS ...
- jQuery中$.extend(true,object1, object2);深拷贝对象
语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 深浅拷贝对应的参数就是[deep],是可选的,为true或false.默认情况是fa ...
- Day4 数据库的建立||数据库对外查询||使用命令行来操作数据库
###数据库的创建 建立一个项目 先进行测试,测试新项目是否可以成功运行 创建一个PersonContrary包,并建立一个Person类实现BaseColumns借口,在此类中添加所有的表的列名,并 ...
- JVM中GC浅解:垃圾回收的了解
1.为什么要有GC 没有GC的世界,我们需要手动进行内存管理,但是内存管理是纯技术活,又容易出错.但是我们写码的目的是为了解决业务问题,所以可以把这种纯技术活自动化,当然自动化也是有代价的. 2.垃圾 ...
- Previous operation has not finished; run 'cleanup' if it was interrupted
在使用myeclipse的时候,点击保存的时候,控制台窗口总是弹出这个svn :Previous operation has not finished; run 'cleanup' if it was ...
- 深入理解CPU和异构计算芯片GPU/FPGA/ASIC (上篇)
王玉伟,腾讯TEG架构平台部平台开发中心基础研发组资深工程师,专注于为数据中心提供高效的异构加速云解决方案.目前,FPGA已在腾讯海量图片处理以及检测领域已规模上线. 随着互联网用户的快速增长,数据体 ...