网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
request.nowInMillis(),
request.filteringAliases()
);
SearchContext searchContext = searchService.createSearchContext(shardSearchLocalRequest, SearchService.NO_TIMEOUT);
try {
ParsedQuery parsedQuery = searchContext.getSearchExecutionContext().toQuery(request.query());
searchContext.parsedQuery(parsedQuery);
searchContext.preProcess();
valid = true;
explanation = explain(searchContext, request.rewrite());
} catch (QueryShardException | ParsingException e) {
valid = false;
error = e.getDetailedMessage();
} catch (AssertionError e) {
valid = false;
error = e.getMessage();
} finally {
Releasables.close(searchContext);
}
return new ShardValidateQueryResponse(request.shardId(), valid, explanation, error);
}
### request.query()
#### ValidateQueryRequestBuilder
public ValidateQueryRequestBuilder setQuery(QueryBuilder queryBuilder) {
request.query(queryBuilder);
return this;
}
### public class RestValidateQueryAction extends BaseRestHandler
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client)
ValidateQueryRequest validateQueryRequest = new ValidateQueryRequest(Strings.splitStringByCommaToArray(request.param(“index”)))
validateQueryRequest.query(RestActions.urlParamsToQueryBuilder(request));
String queryString = request.param(“q”);
QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(queryString);
queryBuilder.analyzer(request.param(“analyzer”));
channel -> {handleException(validateQueryRequest, finalBodyParsingException.getMessage(), channel)};
### AbstractQueryBuilder
#### toQuery
调用子类的 doToQuery 函数
public final Query toQuery(SearchExecutionContext context) throws IOException {
Query query = doToQuery(context);
if (query != null) {
if (boost != DEFAULT_BOOST) {
if (query instanceof MatchNoDocsQuery == false) {
query = new BoostQuery(query, boost);
}
}
if (queryName != null) {
context.addNamedQuery(queryName, query);
}
}
return query;
}
### RestActions
#### urlParamsToQueryBuilder
获取QueryStringQueryBuilder
public static QueryBuilder urlParamsToQueryBuilder(RestRequest request) {
String queryString = request.param(“q”);
if (queryString == null) {
List unconsumedParams = Arrays.stream(queryStringParams).filter(key -> request.param(key) != null).toList();
if (unconsumedParams.isEmpty() == false) {
// this would lead to a non-descriptive error from RestBaseHandler#unrecognized later, so throw a better IAE here
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
“request [%s] contains parameters %s but missing query string parameter ‘q’.”,
request.path(),
unconsumedParams.toString()
)
);
}
return null;
}
QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(queryString);
queryBuilder.defaultField(request.param(“df”));
queryBuilder.analyzer(request.param(“analyzer”));
queryBuilder.analyzeWildcard(request.paramAsBoolean(“analyze_wildcard”, false));
queryBuilder.lenient(request.paramAsBoolean(“lenient”, null));
String defaultOperator = request.param(“default_operator”);
if (defaultOperator != null) {
queryBuilder.defaultOperator(Operator.fromString(defaultOperator));
}
return queryBuilder;
}
### 调用doToQuery函数
获取到 QueryStringQueryParser
protected Query doToQuery(SearchExecutionContext context)
QueryStringQueryParser queryParser;
queryParser = new QueryStringQueryParser(context, resolvedFields, isLenient);
### es跨字段检索实现
SearchExecutionContext context = createSearchExecutionContext();
QB firstQuery = createTestQueryBuilder();
QB controlQuery = copyQuery(firstQuery);
QueryBuilder rewritten = rewriteQuery(firstQuery, new SearchExecutionContext(context));
Query firstLuceneQuery = rewritten.toQuery(context);
### Rewriteable
public interface Rewriteable{
static <T extends Rewriteable> void rewriteAndFetch(
T original,
QueryRewriteContext context,
ActionListener rewriteResponse,
int iteration
) {
T builder = original;
try {
for (T rewrittenBuilder = builder.rewrite(context); rewrittenBuilder != builder; rewrittenBuilder = builder.rewrite(context)) {
builder = rewrittenBuilder;
if (iteration++ >= MAX_REWRITE_ROUNDS) {
// this is some protection against user provided queries if they don’t obey the contract of rewrite we allow 16 rounds
// and then we fail to prevent infinite loops
throw new IllegalStateException(
"too many rewrite rounds, rewriteable might return new objects even if they are not " + “rewritten”
);
}
if (context.hasAsyncActions()) {
T finalBuilder = builder;
final int currentIterationNumber = iteration;
context.executeAsyncActions(
ActionListener.wrap(
n -> rewriteAndFetch(finalBuilder, context, rewriteResponse, currentIterationNumber),
rewriteResponse::onFailure
)
);
return;
}
}
rewriteResponse.onResponse(builder);
} catch (IOException | IllegalArgumentException | ParsingException ex) {
rewriteResponse.onFailure(ex);
}
}
}
### AbstractQueryBuilder类
public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder> implements QueryBuilder
static Collection toQueries(Collection queryBuilders, SearchExecutionContext context) throws QueryShardException,
IOException {
List queries = new ArrayList<>(queryBuilders.size());
for (QueryBuilder queryBuilder : queryBuilders) {
Query query = queryBuilder.rewrite(context).toQuery(context);
if (query != null) {
queries.add(query);
}
}
return queries;
}
public final Query toQuery(SearchExecutionContext context) throws IOException {
Query query = doToQuery(context);
if (query != null) {
if (boost != DEFAULT_BOOST) {
if (query instanceof MatchNoDocsQuery == false) {
query = new BoostQuery(query, boost);
}
}
if (queryName != null) {
context.addNamedQuery(queryName, query);
}
}
return query;
}
### MultiMatchQueryParser实现
MultiMatchQueryParser parser = new MultiMatchQueryParser(searchExecutionContext);
Map<String, Float> fieldNames = new HashMap<>();
fieldNames.put(“field”, 1.0f);
fieldNames.put(“field_split”, 1.0f);
fieldNames.put(“field_normalizer”, 1.0f);
fieldNames.put(“field_split_normalizer”, 1.0f);
Query query = parser.parse(MultiMatchQueryBuilder.Type.BEST_FIELDS, fieldNames, “Foo Bar”, null);
DisjunctionMaxQuery expected = new DisjunctionMaxQuery(
Arrays.asList(
new TermQuery(new Term(“field_normalizer”, “foo bar”)),
new TermQuery(new Term(“field”, “Foo Bar”)),
new BooleanQuery.Builder().add(new TermQuery(new Term(“field_split”, “Foo”)), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(“field_split”, “Bar”)), BooleanClause.Occur.SHOULD)
.build(),
new BooleanQuery.Builder().add(new TermQuery(new Term(“field_split_normalizer”, “foo”)), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(“field_split_normalizer”, “bar”)), BooleanClause.Occur.SHOULD)
.build()
),
0.0f
);
### MultiMatchQueryBuilder
public class MultiMatchQueryBuilder extends AbstractQueryBuilder
protected Query doToQuery(SearchExecutionContext context){
MultiMatchQueryParser multiMatchQuery = new MultiMatchQueryParser(context);
multiMatchQuery.setAnalyzer(analyzer);
multiMatchQuery.setOccur(operator.toBooleanClauseOccur());
multiMatchQuery.setTieBreaker(tieBreaker);
return multiMatchQuery.parse(type, newFieldsBoosts, value, minimumShouldMatch);
}
### MultiMatchQueryParser
public class MultiMatchQueryParser extends MatchQueryParser {
public Query parse(MultiMatchQueryBuilder.Type type, Map<String, Float> fieldNames, Object value, String minimumShouldMatch)
final List queries = switch (type) {
case PHRASE, PHRASE_PREFIX, BEST_FIELDS, MOST_FIELDS, BOOL_PREFIX -> buildFieldQueries(
type,
fieldNames,
value,
minimumShouldMatch
);
case CROSS_FIELDS -> buildCrossFieldQuery(fieldNames, value, minimumShouldMatch, tieBreaker);
};
return combineGrouped(queries, tieBreaker);
return new DisjunctionMaxQuery(groupQuery, tieBreaker);
}
#### buildCrossFieldQuery 核心
跨字段召回的 核心代码,生成一堆 List should链接
叶子是 CrossFieldsQueryBuilder
### lucene检索流程
![在这里插入图片描述](https://img-blog.csdnimg.cn/2000812d430f466abfb2b4dd95fc996a.png)
Analyzer analyzer = new StandardAnalyzer();
Path indexPath = Files.createTempDirectory("tempIndex");
Directory directory = FSDirectory.open(indexPath)
IndexWriterConfig config = new IndexWriterConfig(analyzer);
IndexWriter iwriter = new IndexWriter(directory, config);
Document doc = new Document();
String text = "This is the text to be indexed.";
doc.add(new Field("fieldname", text, TextField.TYPE_STORED));
iwriter.addDocument(doc);
iwriter.close();
// Now search the index:
DirectoryReader ireader = DirectoryReader.open(directory);
IndexSearcher isearcher = new IndexSearcher(ireader);
// Parse a simple query that searches for "text":
QueryParser parser = new QueryParser("fieldname", analyzer);
Query query = parser.parse("text");
ScoreDoc[] hits = isearcher.search(query, 10).scoreDocs;
assertEquals(1, hits.length);
// Iterate through the results:
for (int i = 0; i < hits.length; i++) {
Document hitDoc = isearcher.doc(hits[i].doc);
assertEquals("This is the text to be indexed.", hitDoc.get("fieldname"));
}
ireader.close();
directory.close();
IOUtils.rm(indexPath);
### es检索流程
public TransportSearchAction(
ThreadPool threadPool,
CircuitBreakerService circuitBreakerService,
TransportService transportService,
SearchService searchService,
SearchTransportService searchTransportService,
SearchPhaseController searchPhaseController,
ClusterService clusterService,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
NamedWriteableRegistry namedWriteableRegistry,
ExecutorSelector executorSelector
)
SearchTransportService.registerRequestHandler(transportService, searchService);
transportService.registerRequestHandler(
QUERY_ID_ACTION_NAME,
ThreadPool.Names.SAME,
QuerySearchRequest::new,
(request, channel, task) -> {
searchService.executeQueryPhase(
request,
(SearchShardTask) task,
new ChannelActionListener<>(channel, QUERY_ID_ACTION_NAME, request)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ew ChannelActionListener<>(channel, QUERY_ID_ACTION_NAME, request)
[外链图片转存中…(img-dfdm1Ogg-1715557939595)]
[外链图片转存中…(img-QN1jQL5d-1715557939596)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!