对于刚接触搜索或者Elasticsearch的小白来说对queryString可能接触的不多,但是对于早期从事搜索的人来说queryString并不会陌生,它可以理解成检索表达式,但并不是elasticsearch的queryDSL,他遵从的是Lucene语法。elasticsearch同样有接口应用于queryString。下面上个例子:

{"from": 0,"size": 100,"query": {"query_string": {"query": "TITLE:无人机"}}
}

“TITLE:无人机”就是一个queryString,是一个字符串,表示在TITLE字段中查询匹配“无人机”。
它还支持一些参数:

{"from": 0,"size": 100,"query": {"query_string": {"query": "TITLE:无人机""fields": [],"type": "best_fields","default_operator": "or","max_determinized_states": 10000,"enable_position_increments": true,"fuzzy_transpositions": true,"boost": 1}}
}

具体的关于queryString本篇不再过多介绍,这里不是重点。

参考官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html

从上述例子中我们知道了我们的需求是从TITLE中匹配“无人机”这个词。这个检索式没任何问题,因为一般的分词器都会把无人机这个词分出来,但随着我们检索的深入,我们会遇到一个问题,比如我们要搜索“铝合金轮毂”这个词,一般的分词器都不会分出这个词来,也就是我们所说的专有名词词库。那么会出现什么问题呢?我们试试就知道了

{"query": {"query_string": {"query": "TITLE:铝合金轮毂"}}
}

我们会发现匹配结果包含很多铝合金和轮毂的文档,可想而知是因为在检索的时候,是先把“铝合金轮毂‘这个词先分词,再去检索的,类似match检索。那么这样的话就会带来两个问题:

  1. 如果我不想用match,我想精准匹配只返回带“铝合金轮毂”而不是“铝合金”+“轮毂”怎么办?
  2. 如果词库里没有“铝合金轮毂”这个词,该怎么做精准匹配?

说到这,可能有些人就会说了,你把“铝合金轮毂”这个词加上引号不就行了。我们来具体看看行还是不行:

{"query": {"query_string": {"query": "TITLE:\"铝合金轮毂\""}}
}

我们还引号的目的是想做精准匹配,的确,早期的lucene的确是这么做的。从返回结果上看,也的确达到了我们想要的记过——只返回“铝合金轮毂”。但是我想告诉大家的是,这其实是早期Lucene的一个bug,在Lucene4中已经被修复了——将检索词加引号并不是实现精准匹配。

下面我们开始验证。

{"query": {"term": {"TITLE": "铝合金轮毂"}}
}

我们使用term检索来验证,前面已经说到词库里是没有“铝合金轮毂”这个词的,也就是说分词器不会将“铝合金轮毂”作为倒排的一个term进行索引。这样来说,这个检索必然是没有数据返回,我们找一句话验证一下。

GET _analyze?pretty
{"analyzer": "ik_max_word","text": "某汽车铝合金轮毂在使用一年后发现裂纹"
}

我们使用ik_max分词,避免有些猩猩不服,下面是分词结果:

{"tokens": [{"token": "某","start_offset": 0,"end_offset": 1,"type": "CN_CHAR","position": 0},{"token": "汽车","start_offset": 1,"end_offset": 3,"type": "CN_WORD","position": 1},{"token": "铝合金","start_offset": 3,"end_offset": 6,"type": "CN_WORD","position": 2},{"token": "合金","start_offset": 4,"end_offset": 6,"type": "CN_WORD","position": 3},{"token": "轮毂","start_offset": 6,"end_offset": 8,"type": "CN_WORD","position": 4},{"token": "在","start_offset": 8,"end_offset": 9,"type": "CN_CHAR","position": 5},{"token": "使用","start_offset": 9,"end_offset": 11,"type": "CN_WORD","position": 6},{"token": "一年","start_offset": 11,"end_offset": 13,"type": "CN_WORD","position": 7},{"token": "一","start_offset": 11,"end_offset": 12,"type": "TYPE_CNUM","position": 8},{"token": "年后","start_offset": 12,"end_offset": 14,"type": "CN_WORD","position": 9},{"token": "年","start_offset": 12,"end_offset": 13,"type": "COUNT","position": 10},{"token": "后","start_offset": 13,"end_offset": 14,"type": "CN_CHAR","position": 11},{"token": "发现","start_offset": 14,"end_offset": 16,"type": "CN_WORD","position": 12},{"token": "裂纹","start_offset": 16,"end_offset": 18,"type": "CN_WORD","position": 13}]
}

从结果中可以发现,并没有“铝合金轮毂”这个词,所以这个时候使用term检索是不会检索到这条数据的。那为什么用querySring就可以检索的到呢?
因为我们主观带入的认为加上引号就是做了精准匹配,实际上早期的Lucene的确是这样,但这是Lucene的一个bug,早已经被修复了,修复的结果是queryString中带引号的检索词并不是使用精准匹配,而是使用短语匹配。

我们在使用Elasticsearch的过程中可能使用term和match的时候是最多的,用到短语匹配的可能并不是很多。但在特定的场景中,短语匹配的效果要远好于term和match。

{"query": {"match_phrase" : {"TITLE" : "铝合金轮毂","slop": 0}}
}

match_phrase为短语匹配,短语匹配同样是先将检索词分词,支持自定义分词“analyzer”:“my_analyzer”,一般建议使用和索引分词同一个分词器的检索效果更好。与match不同的是在于参数slop,官方给的解释是

A phrase query matches terms up to a configurable slop (which defaults to 0) in any order. Transposed terms have a slop of 2.

翻大概意思就是允许分词匹配顺序错误的次数, “slop”: 0表示不允许顺序错误,这样即使将“铝合金”和“轮毂”分开,但是结果中必须是“铝合金”和“轮毂”挨着的才会被检索到,同样可以实现term的检索效果。

以上就是使用queryString检索词加不加引号,以及如何检索精确检索词库中不存在的词的介绍。

附1

match检索一直有一个通病,就是不支持多个检索词(例如terms),会报错。网上找了很多资料,国内的各大网上均没有相关介绍,最终在国外的网站找到了相似的:跳转链接 和 github相关iss

{"query": {"match" : {"TITLE" : ["铝合金","轮毂"]}}
}

这种检索式会报错:

{"error": {"root_cause": [{"type": "illegal_state_exception","reason": "Can't get text on a START_ARRAY at 1:28"}],"type": "illegal_state_exception","reason": "Can't get text on a START_ARRAY at 1:28"},"status": 500
}

所以我们可以这么做:

{"query": {"bool": {"must": [{"match": {"TITLE": "铝合金"}},{"match": {"TITLE": "轮毂"}}]}}
}

附2

前面提到match_phrase可以通过"slop": 0来实现term的效果,脑洞大开的猩猩们肯定会想到,那我是不是可以通过控制slop参数来实现match检索的功能了呢?答案是不建议。虽然PhraseQuery也会进行打分,但是打分效果远没有BooleanQuery效果好,所以不建议这么使用,无论是terms还是match比这都要好得多。

总结

本片文章介绍了Lucene的queryString检索词加不加引号的区别,以及如何使用term、match来进行检索匹配。如何对词库中没有的词进行精确匹配,以及match不支持数组参数等问题进行探究。

作为整个Elasticsearch干货系列的开篇,内容可能不多,但这的确是困扰了我很久的一个问题,在这里分享给大家,主要还是相关资料太少。我们的老集群已经运行很多年了, 还是0.9版本的集群,那个年代的搜索引擎和现在差别太大了。在这里跟一些初学者说,无论你是学习搜索还是Elasticsearch,一定要学习Lucene,不管Elasticsearch还是以前的solr,他们能够强大,是因为Lucene是全世界最好的搜索引擎,千遍万遍底层技术十年不变。

后续会不定期更新干货系列,非常希望大家能够一起沟通,Elasticsearch越学你会越发现,它非常有趣。

更多文章关注公众号

Elasticsearch干货(九):queryString中检索词加不加引号?相关推荐

  1. 【nginx配置】 proxy_pass反向代理配置中url后面加不加/的说明

    在日常的web网站部署中,经常会用到nginx的proxy_pass反向代理,有一个配置需要弄清楚:配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把loca ...

  2. js创建对象时,属性加引号与不加引号的区别(转)

    概要: 总结一下: 1. 命名要规范,变量名或者属性名不能用数字开头. 2. 可以加引号后使用,但调用要像数组中的属性那样调用  obj['888name'] 3. 符合规范的时候,加不加引号一样 以 ...

  3. 关于电商搜索中Elasticsearch的正确使用姿势--检索篇

    文章目录 前言 检索的前一步 检索 分数 sort operator 二次召回 改变权重 组合查询 归因问题(functionScore) 聚合 结语 前言 书接上文,我们为电商项目做了个性化的索引配 ...

  4. Elasticsearch中基于词项的搜索

    为了方便我们学习,我们导入kibana为我们提供的范例数据. 目前为止,我们已经探索了如何将数据放入Elasticsearch,现在来讨论下如何将数据从Elasticsearch中拿出来,那就是通过搜 ...

  5. 搜索引擎中输入检索词到返回十条结果,发生了哪些事情

    移动互联网时代搜索引擎依然是重要流量来源以及流量分发渠道,虽然比PC互联网时代权重有所降低. 各大电商淘宝.京东80-90%交易额也是由用户app内搜索.网站内搜索产生,个性化推荐系统本身也和搜索 引 ...

  6. html中讲关键字加粗体,关键字(词)加粗 SEO

    关键字为什么要加粗,关键字(词)加粗可以提高SEO排名吗,关键字加粗的作用是什么? 关键字加粗有两个作用,如下: 一:注释作用,让用户和搜索引擎知道这是一组加粗文字. 二:提醒作用,引起用户和搜索引擎 ...

  7. ElasticSearch 在 Spring 项目中的实践

    前言 ElasticSearch简称es,是一个开源的高扩展的分布式全文检索引擎. 它可以近乎实时的存储.检索数据,其扩展性很好,ElasticSearch是企业级应用中较为常见的技术. 下面和大家分 ...

  8. 面试精讲之面试考点及大厂真题 - 分布式专栏 17 ElasticSearch解决大数据量检索难题

    17 ElasticSearch解决大数据量检索难题 理想的书籍是智慧的钥匙. --列夫·托尔斯泰 引言 如果你的项目里有超过千万上亿级别的数据,且数据日增量较大需要高性能检索时,如订单数据,你该怎么 ...

  9. BERT中的词向量指南

    2019-11-19 20:50:57 作者:Chris McCormick 编译:ronghuaiyang 导读 在本文中,我将深入研究谷歌的BERT生成的word embeddings,并向你展示 ...

  10. python实用大全pdf_超级实用干货|九大技巧,带你用Python玩转PDF

    原标题:超级实用干货|九大技巧,带你用Python玩转PDF 尽管PDF最开始是由Adobe发明的,但它现在已经成为国际标准组织ISO维护的公开标准了.大家可以在Python中通过PyPDF2包来处理 ...

最新文章

  1. Android 中文api (88)——SharedPreferences
  2. unity3d游戏开发第2版 pdf_学开发2个月,1个人做出个TapTap排行榜第4的游戏?
  3. TurboMail邮件系统通过涉密信息系统产品认定
  4. java判断字符串有中文_JAVA入门之正则表达式判断字符串包含中文
  5. 没有语言基础可以学python_没有Python语言基础可以学习深度学习吗?
  6. 如何对web.config进行加密和解密
  7. BestCoder Round #77 (div.2)解题报告
  8. C ++中的初始化程序列表– std :: initializer_list
  9. ZOJ Monthly, March 2018 A Easy Number Game
  10. 云原生时代——投资人视角下的云原生趋势思考
  11. [转]王飞跃:交通拥堵多因管理水平等所致
  12. word删除分页符的两种方法
  13. 跑步耳机哪款好用,排行前五的运动耳机推荐
  14. 双曲三角函数图像及计算
  15. Unity 接入百度AI - 动物识别
  16. Android开发指南
  17. GPU的发展史,GPU与CPU的关系是什么?为何现在GPU越来越重要?
  18. 获取分时数据,日k数据(A股,港股,美股)
  19. java用mysql方便吗_面试题总结:可能是全网最好的MySQL重要知识点
  20. 云计算——网络布线(1)

热门文章

  1. 基于Android的医院挂号系统设计与实现(MySQL+Spring Boot+MyBatis+Android Studio+IDEA)
  2. Linux/Ubuntu的常用文件查找命令
  3. 世界金融发展史:从资产证券化到STO
  4. 【Error】Android: java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepa
  5. 科普:ARM的授权方式
  6. 未来已来 云上安全SaaS化势不可挡
  7. 削峰填谷,你只知道消息队列?
  8. 微软邮箱(@outlook.com/@hotmail.com):双重验证+应用密码
  9. 计算机专业29岁研究生毕业,26岁,你还会考研吗?毕业后都奔三了!_计算机考研科目...
  10. android渠道首发规则,酷传推广标准手册-android渠道首发规则.doc