Elasticsearch源码分析六--调用Lucene查询接口之前缀查询(Prefix)
2016-05-10 15:20
579 查看
简介
查询语法
源码分析
字段以给定的前缀开始。。
{
“query” : {
“prefix” : {
“title” : {
“value” : “cri”,
“boost” : 3.0
}}}}
查询语法
源码分析
简介
前缀查询在配置方面来说跟词条查询类似。前缀查询能让我们匹配这样的文档:它们的特定字段以给定的前缀开始。。
查询语法
例:查找所有title字段以cri开始的文档:{
“query” : {
“prefix” : {
“title” : {
“value” : “cri”,
“boost” : 3.0
}}}}
源码分析
'''(1)Elasticsearch code''' public class PrefixQueryParser implements QueryParser { public static final String NAME = "prefix"; @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(), "[prefix] query malformed, no field"); } String fieldName = parser.currentName(); String rewriteMethod = null; Object value = null; float boost = 1.0f; 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 (token.isValue()) { if ("prefix".equals(currentFieldName)) { value = parser.objectBytes(); } else if ("value".equals(currentFieldName)) { value = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("rewrite".equals(currentFieldName)) { rewriteMethod = parser.textOrNull(); } } else { throw new QueryParsingException(parseContext.index(), "[prefix] query does not support [" + currentFieldName + "]"); } } parser.nextToken(); } else { value = parser.text(); parser.nextToken(); } if (value == null) { throw new QueryParsingException(parseContext.index(), "No value specified for prefix query"); } MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(rewriteMethod, null); Query query = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { if (smartNameFieldMappers.explicitTypeInNameWithDocMapper()) { String[] previousTypes = QueryParseContext.setTypesWithPrevious(new String[]{smartNameFieldMappers.docMapper().type()}); try { query = smartNameFieldMappers.mapper().prefixQuery(value, method, parseContext); } finally { QueryParseContext.setTypes(previousTypes); } } else { query = smartNameFieldMappers.mapper().prefixQuery(value, method, parseContext); } } if (query == null) { '''构造Lucene的PrefixQuery对象(Term("title","cri"))''' PrefixQuery prefixQuery = new PrefixQuery(new Term(fieldName, BytesRefs.toBytesRef(value))); '''设置重写方法,将cri重写为索引中以cri开始的词,这些词以或的关系组织''' if (method != null) { prefixQuery.setRewriteMethod(method); } query = prefixQuery; } query.setBoost(boost); return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext); } } '''(2)Lucene code''' public class PrefixQuery extends AutomatonQuery { .... } public class AutomatonQuery extends MultiTermQuery { .... } public abstract class MultiTermQuery extends Query { .... @Override '''PrefixQuery是MultiTermQuery的子类,调用父类的rewrite方法''' public final Query rewrite(IndexReader reader) throws IOException { return rewriteMethod.rewrite(reader, this); } } '''(3)Lucene 常用词查询举例''' public void testPrefixQuery() throws Exception { Directory directory = newDirectory(); String[] categories = new String[] {"/Computers", "/Computers/Mac", "/Computers/Windows"}; RandomIndexWriter writer = new RandomIndexWriter(random(), directory); for (int i = 0; i < categories.length; i++) { Document doc = new Document(); doc.add(newStringField("category", categories[i], Field.Store.YES)); writer.addDocument(doc); } IndexReader reader = writer.getReader(); '''查找category字段中以"/Computers"开始的文档''' PrefixQuery query = new PrefixQuery(new Term("cat bf86 egory", "/Computers")); IndexSearcher searcher = newSearcher(reader); ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs; assertEquals("All documents in /Computers category and below", 3, hits.length); '''查找category字段中以"/Computers/Mac"开始的文档''' query = new PrefixQuery(new Term("category", "/Computers/Mac")); hits = searcher.search(query, 1000).scoreDocs; assertEquals("One in /Computers/Mac", 1, hits.length); '''查找category字段中以任何字符串开始的文档即所有文档''' query = new PrefixQuery(new Term("category", "")); hits = searcher.search(query, 1000).scoreDocs; assertEquals("everything", 3, hits.length); writer.close(); reader.close(); directory.close(); }
相关文章推荐
- 巧用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高亮显示