QueryParser及其子类用于对输入的查询query进行解析,返回Query类的对象,代表具体的查询类。
Elasticsearch为每种类型的Query提供了单独的查询解析器;而Lucene的QueryParser对所有类型的Query使用相同的查询解析器。
Lucene的解析器使用如下:
'''在构造QueryParser对象时传入分析器,此过程涉及JavaCC、分词器、查询语法等'''
QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "contents", new StandardAnalyzer(Version.LUCENE_CURRENT));
Query query = parser.parse("+(+apple* -boy) (cat* dog) -(eat~ foods)");
'''(1)添加Query解析器及Filter解析器的实例对象'''
public class IndicesQueriesModule extends AbstractModule {
protected void configure() {
bind(IndicesQueriesRegistry.class).asEagerSingleton();
Multibinder qpBinders = Multibinder.newSetBinder(binder(), QueryParser.class);
for (Class queryParser : queryParsersClasses) {
qpBinders.addBinding().to(queryParser).asEagerSingleton();
}
for (QueryParser queryParser : queryParsers) {
qpBinders.addBinding().toInstance(queryParser);
}
'''(1)添加Query解析器实例对象''' qpBinders.addBinding().to(MatchQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(MultiMatchQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(NestedQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(HasChildQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(HasParentQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(TopChildrenQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(DisMaxQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(IdsQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(MatchAllQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(QueryStringQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(BoostingQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(BoolQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(TermQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(TermsQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(FuzzyQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(RegexpQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(FieldQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(RangeQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(PrefixQueryParser.class).asEagerSingleton();
qpBinders.addBinding().to(WildcardQueryParser.class).asEagerSingleton();
'''省略...'''
'''(2)添加Filter解析器实例对象''' fpBinders.addBinding().to(HasChildFilterParser.class).asEagerSingleton();
fpBinders.addBinding().to(HasParentFilterParser.class).asEagerSingleton();
'''省略...'''
}
}
'''(2)Query/Filter类型-Query/Filter解析器实例对象对应关系注册'''
public class IndexQueryParserService extends AbstractIndexComponent {
'''Query类型-Query解析器实例对象映射关系'''
private final Map queryParsers;
'''Filter类型-Filter解析器实例对象映射关系'''
private final Map filterParsers;
public IndexQueryParserService(Index index, @IndexSettings Settings indexSettings,
IndicesQueriesRegistry indicesQueriesRegistry, CacheRecycler cacheRecycler,
ScriptService scriptService, AnalysisService analysisService,
MapperService mapperService, IndexCache indexCache, IndexFieldDataService fieldDataService, IndexEngine indexEngine,
@Nullable SimilarityService similarityService,
@Nullable Map namedQueryParsers,
@Nullable Map namedFilterParsers) {
super(index, indexSettings);
this.cacheRecycler = cacheRecycler;
this.scriptService = scriptService;
this.analysisService = analysisService;
this.mapperService = mapperService;
this.similarityService = similarityService;
this.indexCache = indexCache;
this.fieldDataService = fieldDataService;
this.indexEngine = indexEngine;
this.defaultField = indexSettings.get("index.query.default_field", AllFieldMapper.NAME);
this.queryStringLenient = indexSettings.getAsBoolean("index.query_string.lenient", false);
List queryParsers = newArrayList();
if (namedQueryParsers != null) {
Map queryParserGroups = indexSettings.getGroups(IndexQueryParserService.Defaults.QUERY_PREFIX);
for (Map.Entry entry : namedQueryParsers.entrySet()) {
String queryParserName = entry.getKey();
QueryParserFactory queryParserFactory = entry.getValue();
Settings queryParserSettings = queryParserGroups.get(queryParserName);
if (queryParserSettings == null) {
queryParserSettings = EMPTY_SETTINGS;
}
queryParsers.add(queryParserFactory.create(queryParserName, queryParserSettings));
}
}
Map queryParsersMap = newHashMap();
queryParsersMap.putAll(indicesQueriesRegistry.queryParsers());
if (queryParsers != null) {
'''添加Query类型-Query解析器实例对象到Map中'''
for (QueryParser queryParser : queryParsers) {
add(queryParsersMap, queryParser);
}
}
this.queryParsers = ImmutableMap.copyOf(queryParsersMap);
List filterParsers = newArrayList();
if (namedFilterParsers != null) {
Map filterParserGroups = indexSettings.getGroups(IndexQueryParserService.Defaults.FILTER_PREFIX);
for (Map.Entry entry : namedFilterParsers.entrySet()) {
String filterParserName = entry.getKey();
FilterParserFactory filterParserFactory = entry.getValue();
Settings filterParserSettings = filterParserGroups.get(filterParserName);
if (filterParserSettings == null) {
filterParserSettings = EMPTY_SETTINGS;
}
filterParsers.add(filterParserFactory.create(filterParserName, filterParserSettings));
}
}
Map filterParsersMap = newHashMap();
filterParsersMap.putAll(indicesQueriesRegistry.filterParsers());
if (filterParsers != null) {
'''添加Filter类型-Filter解析器实例对象到Map中'''
for (FilterParser filterParser : filterParsers) {
add(filterParsersMap, filterParser);
}
}
this.filterParsers = ImmutableMap.copyOf(filterParsersMap);
}
}
'''(3)提供接口根据name获取解析器实例对象'''
public class IndexQueryParserService extends AbstractIndexComponent {
'''根据Query名字获取Query解析器实例对象'''
public QueryParser queryParser(String name) {
return queryParsers.get(name);
}
'''根据Filter名字获取Filter解析器实例对象'''
public FilterParser filterParser(String name) {
return filterParsers.get(name);
}
}
'''(4)Map的Key定义即Query类型和Filter类型来源'''
public class WildcardQueryParser implements QueryParser {
'''Query类型定义'''
public static final String NAME = "wildcard";
@Override
'''Query类型获取接口'''
public String[] names() {
return new String[]{NAME};
}
}
public class PrefixFilterParser implements FilterParser {
'''Filter类型'''
public static final String NAME = "prefix";
'''Filter类型获取接口'''
@Override
public String[] names() {
return new String[]{NAME};
}
}