在做搜索的时候,下拉联想词的搜索肯定是最常见的一个场景,用户在输入的时候,要自动补全词干,说得简单点,就是以...开头搜索,如果是数据库,一句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 '?%' 搜索的更多相关文章

  1. 转:在ElasticSearch之下(图解搜索的故事)

    ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事) 摘要 先自上而下,后自底向上的介绍ElasticSearch的底层工作原理,试图回答以下问题: 为什么我 ...

  2. Elasticsearch java api 基本搜索部分详解

    文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...

  3. ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事)

    ElasticSearch 2 (9) - 在ElasticSearch之下(图解搜索的故事) 摘要 先自上而下,后自底向上的介绍ElasticSearch的底层工作原理,试图回答以下问题: 为什么我 ...

  4. ElasticSearch 2 (18) - 深入搜索系列之控制相关度

    ElasticSearch 2 (18) - 深入搜索系列之控制相关度 摘要 处理结构化数据(比如:时间.数字.字符串.枚举)的数据库只需要检查一个文档(或行,在关系数据库)是否与查询匹配. 布尔是/ ...

  5. ElasticSearch 2 (17) - 深入搜索系列之部分匹配

    ElasticSearch 2 (17) - 深入搜索系列之部分匹配 摘要 到目前为止,我们介绍的所有查询都是基于完整术语的,为了匹配,最小的单元为单个术语,我们只能查找反向索引中存在的术语. 但是, ...

  6. ElasticSearch 2 (16) - 深入搜索系列之近似度匹配

    ElasticSearch 2 (16) - 深入搜索系列之近似度匹配 摘要 标准的全文搜索使用TF/IDF处理文档.文档里的每个字段或一袋子词.match 查询可以告诉我们哪个袋子里面包含我们搜索的 ...

  7. ElasticSearch 2 (15) - 深入搜索系列之多字段搜索

    ElasticSearch 2 (15) - 深入搜索系列之多字段搜索 摘要 查询很少是简单的一句话匹配(one-clause match)查询.很多时候,我们需要用相同或不同的字符串查询1个或多个字 ...

  8. ElasticSearch 2 (13) - 深入搜索系列之结构化搜索

    ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ...

  9. Ajax以及类似百度搜索框的demo

    public class Ajax01 extends HttpServlet{ @Override protected void service(HttpServletRequest request ...

随机推荐

  1. 对java数组的一些理解

    刚开始学习Java的时候一直搞不清除获取数组的长度是用length()还是length,现在不妨来深入了解一下数组的真实面目. 我们不妨来看一下数组的源码,诶,数组的类名叫什么?我们声明一个int数组 ...

  2. 读书笔记 effective c++ Item 29 为异常安全的代码而努力

    异常安全在某种意义上来说就像怀孕...但是稍微想一想.在没有求婚之前我们不能真正的讨论生殖问题. 假设我们有一个表示GUI菜单的类,这个GUI菜单有背景图片.这个类将被使用在多线程环境中,所以需要mu ...

  3. 前端布局常见IE6 bug的解决方法,清除浮动的几种方法以及各自的优缺点

    相信有很多前端的朋友再布局的时候经常面对IE6咬牙切齿,尤其是刚刚入行的朋友,在这里给大家一点常见问题的解决方案,希望对大家有所帮助 1)png24位的图片在iE6浏览器上出现背景,解决方案是做成PN ...

  4. maven配置文件setting.xml字段注释

    maven的配置文件为settings.xml,在下面路径中可以找到这个文件,分别为: $M2_HOME/conf/settings.xml:全局设置,在maven的安装目录下: ${user.hom ...

  5. BOM基础(一)

    学完了js的基础语法和DOM之后,就要要看看javascript中最后一项BOM了.BOM,全称brower document model,翻译过来就是浏览器对象模型.DOM是文档对象模型,属于BOM ...

  6. KoaHub.JS用于Node.js的可移植Unix shell命令程序代码

    shelljs Portable Unix shell commands for Node.js ShellJS - Unix shell commands for Node.js     Shell ...

  7. Oracle-orclEXORIM

    imp pzhdb/hiway@orcl file =d:\pzhsd.dmp fromuser = pzhsd touser=pzhdb:导入 第一个pzhdb为新的用户名 hiway为密码 orc ...

  8. 使用Func<>和Action简化委托

    /// <summary> /// 入口 /// </summary> public void Run() { TestDelegate t = test; t(); Acti ...

  9. 意外发现的大批量导入数据SqlBulkCopy类

    因为要做一个号码归属地查询小功能,因为要导入外部(文本文件)的电话归属地数据,使用的是SqlDataAdapter类,数据不多,只四万有多条,表也只有一个,phoneBook表,使用的是DataTab ...

  10. windows 下编译php扩展库pecl里的扩展memcache

    Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像.视频.文件以及数据库检索的结果等.简单的说就是将数据调用到内 ...