Elasticsearch源码分析五--调用Lucene查询接口之模糊查询(Fuzzy)
2016-05-10 14:58
851 查看
简介
查询语法
源码分析
{
“query” : {
“fuzzy” : {
“title” : {
“value” : “think~”,
“min_similarity” : 0.2
}}}}
min_similarity:指定了一个词条被算作匹配所必须拥有的最小相似度。对字符串字段来说,这个值应该在0到1之间,包含0和1。对于数值型字段,这个值可以大于1,比如查询值是20, 设为3,则可以得到17~23的值。对于日期字段,可以把参数值设为1d、 2d、 1m等,分别表示1天、 2天、 1个月。
查询语法
源码分析
简介
模糊查询是基于编辑距离算法来匹配文档。编辑距离的计算基于我们提供的查询词条和被搜索文档。此查询很占用CPU资源。可以在搜索词的尾部加上字符 “~” 来进行模糊查询。查询语法
例如,查询语句 “think~” 返回所有包含和 think 类似的关键词的文档。增量因子(boost factor)为0.2。{
“query” : {
“fuzzy” : {
“title” : {
“value” : “think~”,
“min_similarity” : 0.2
}}}}
min_similarity:指定了一个词条被算作匹配所必须拥有的最小相似度。对字符串字段来说,这个值应该在0到1之间,包含0和1。对于数值型字段,这个值可以大于1,比如查询值是20, 设为3,则可以得到17~23的值。对于日期字段,可以把参数值设为1d、 2d、 1m等,分别表示1天、 2天、 1个月。
源码分析
'''(1)Elasticsearch code''' public class FuzzyQueryParser implements QueryParser { public static final String NAME = "fuzzy"; @Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); if (token != XContentParser.Token.FIELD_NAME) { throw new QueryParsingException(parseContext.index(), "[fuzzy] query malformed, no field"); } String fieldName = parser.currentName(); String value = null; float boost = 1.0f; //LUCENE 4 UPGRADE we should find a good default here I'd vote for 1.0 -> 1 edit String minSimilarity = "0.5"; int prefixLength = FuzzyQuery.defaultPrefixLength; int maxExpansions = FuzzyQuery.defaultMaxExpansions; boolean transpositions = false; MultiTermQuery.RewriteMethod rewriteMethod = null; token = parser.nextToken(); if (token == XContentParser.Token.START_OBJECT) { String currentFieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else { if ("term".equals(currentFieldName)) { value = parser.text(); } else if ("value".equals(currentFieldName)) { value = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("min_similarity".equals(currentFieldName) || "minSimilarity".equals(currentFieldName)) { minSimilarity = parser.text(); } else if ("prefix_length".equals(currentFieldName) || "prefixLength".equals(currentFieldName)) { prefixLength = parser.intValue(); } else if ("max_expansions".equals(currentFieldName) || "maxExpansions".equals(currentFieldName)) { maxExpansions = parser.intValue(); } else if ("transpositions".equals(currentFieldName)) { transpositions = parser.booleanValue(); } else if ("rewrite".equals(currentFieldName)) { rewriteMethod = QueryParsers.parseRewriteMethod(parser.textOrNull(), null); } else { throw new QueryParsingException(parseContext.index(), "[fuzzy] query does not support [" + currentFieldName + "]"); } } } parser.nextToken(); } else { value = parser.text(); // move to the next token parser.nextToken(); } if (value == null) { throw new QueryParsingException(parseContext.index(), "No value specified for fuzzy query"); } Query query = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers != null) { if (smartNameFieldMappers.hasMapper()) { query = smartNameFieldMappers.mapper().fuzzyQuery(value, minSimilarity, prefixLength, maxExpansions, transpositions); } } if (query == null) { //LUCENE 4 UPGRADE we need to document that this should now be an int rather than a float int edits = FuzzyQuery.floatToEdits(Float.parseFloat(minSimilarity), value.codePointCount(0, value.length())); '''构造Lucene的FuzzyQuery对象,参数包括查询Term、编辑距离、匹配的公共前缀长度、查询可被扩展到的最大词条数''' query = new FuzzyQuery(new Term(fieldName, value), edits, prefixLength, maxExpansions, transpositions); } if (query instanceof MultiTermQuery) { QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod); } query.setBoost(boost); return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext); } } '''(2)Lucene code''' '''FuzzyQuery是MultiTermQuery的子类,调用父类的rewrite方法,需要将查询词"think~"重写成think、thinking等索引中存在的词,然后合并这些词的倒排表''' public class FuzzyQuery extends MultiTermQuery { ... } public abstract class MultiTermQuery extends Query { @Override public final Query rewrite(IndexReader reader) throws IOException { return rewriteMethod.rewrite(reader, this); }
相关文章推荐
- 巧用mysql提示符prompt清晰管理数据库的方法
- PHP strtotime函数用法、实现原理和源码分析
- jQuery 源码分析笔记(3) Deferred机制
- jQuery 源码分析笔记(5) jQuery.support
- jQuery-1.9.1源码分析系列(十)事件系统之事件包装
- 两大步骤教您开启MySQL 数据库远程登陆帐号的方法
- java Lucene 中自定义排序的实现
- phpmyadmin 4+ 访问慢的解决方法
- linux系统下实现mysql热备份详细步骤(mysql主从复制)
- CentOS 5.5下安装MySQL 5.5全过程分享
- MySQL复制的概述、安装、故障、技巧、工具(火丁分享)
- MySQL中删除重复数据的简单方法
- Cocos2d-x学习笔记之Hello World源码分析
- PHP源码分析之变量的存储过程分解
- 使用Java的Lucene搜索工具对检索结果进行分组和分页
- 使用ElasticSearch6.0快速实现全文搜索功能的示例代码
- 深入浅析TomCat Session管理分析
- elasticsearch批量数据导入和导出
- 关于lucene搜索时排序的问题
- Lucene highlighter高亮显示