elasticsearch源码分析-08Serch查询流程

Serch查询流程

查询请求Rest路由注册也是在actionModule中

//查询操作
registerHandler.accept(new RestSearchAction());

@Override
public List<Route> routes() {
   
    return unmodifiableList(asList(
        new Route(GET, "/_search"),
        new Route(POST, "/_search"),
        new Route(GET, "/{index}/_search"),
        new Route(POST, "/{index}/_search"),
        // Deprecated typed endpoints.
        new Route(GET, "/{index}/{type}/_search"),
        new Route(POST, "/{index}/{type}/_search")));
}

和Get查询一样,请求会经过转发dispatchRequest,查询路由对应的handler处理类,然后执行处理

@Override
    public void dispatchRequest(RestRequest request, RestChannel channel, ThreadContext threadContext) {
   
        //小图标请求处理
        if (request.rawPath().equals("/favicon.ico")) {
   
            handleFavicon(request.method(), request.uri(), channel);
            return;
        }
        try {
   
            //处理rest请求
            tryAllHandlers(request, channel, threadContext);
        } catch (Exception e) {
   
            try {
   
                channel.sendResponse(new BytesRestResponse(channel, e));
            } catch (Exception inner) {
   
                inner.addSuppressed(e);
                logger.error(() ->
                    new ParameterizedMessage("failed to send failure response for uri [{}]", request.uri()), inner);
            }
        }
    }

调用BaseRestHandler的handleRequest方法

@Override
    public final void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
   
        // prepare the request for execution; has the side effect of touching the request parameters
        //处理请求
        final RestChannelConsumer action = prepareRequest(request, client);

        // validate unconsumed params, but we must exclude params used to format the response
        // use a sorted set so the unconsumed parameters appear in a reliable sorted order
        final SortedSet<String> unconsumedParams =
            request.unconsumedParams().stream().filter(p -> !responseParams().contains(p)).collect(Collectors.toCollection(TreeSet::new));

        // validate the non-response params
        if (!unconsumedParams.isEmpty()) {
   
            final Set<String> candidateParams = new HashSet<>();
            candidateParams.addAll(request.consumedParams());
            candidateParams.addAll(responseParams());
            throw new IllegalArgumentException(unrecognized(request, unconsumedParams, candidateParams, "parameter"));
        }

        if (request.hasContent() && request.isContentConsumed() == false) {
   
            throw new IllegalArgumentException("request [" + request.method() + " " + request.path() + "] does not support having a body");
        }

        usageCount.increment();
        // execute the action
        action.accept(channel);
    }

首先构造请求request对象,RestSearchAction对该方法进行了重写

@Override
    public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
   
        //创建查询请求对象
        SearchRequest searchRequest = new SearchRequest();
        IntConsumer setSize = size -> searchRequest.source().size(size);
        request.withContentOrSourceParamParserOrNull(parser ->
            parseSearchRequest(searchRequest, request, parser, setSize));

        return channel -> {
   
            RestCancellableNodeClient cancelClient = new RestCancellableNodeClient(client, request.getHttpChannel());
            cancelClient.execute(SearchAction.INSTANCE, searchRequest, new RestStatusToXContentListener<>(channel));
        };
    }

首先根据请求的request解析成查询请求

public static void parseSearchRequest(SearchRequest searchRequest, RestRequest request,
                                          XContentParser requestContentParser,
                                          IntConsumer setSize) throws IOException {
   
        //查询源包含哪些字段,为空查询所有字段
        if (searchRequest.source() == null) {
   
            searchRequest.source(new SearchSourceBuilder());
        }
        //查询索引
        searchRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
        if (requestContentParser != null) {
   
            searchRequest.source().parseXContent(requestContentParser, true);
        }
        //协调节点的保护,从每个shard获取的数据最大数据量
        final int batchedReduceSize = request.paramAsInt("batched_reduce_size", searchRequest.getBatchedReduceSize());
        searchRequest.setBatchedReduceSize(batchedReduceSize);
        //预过滤分片数量
        if (request.hasParam("pre_filter_shard_size")) {
   
            searchRequest.setPreFilterShardSize(request.paramAsInt("pre_filter_shard_size", SearchRequest.DEFAULT_PRE_FILTER_SHARD_SIZE));
        }
        //分片并发查询数量
        if (request.hasParam("max_concurrent_shard_requests")) {
   
            // only set if we have the parameter since we auto adjust the max concurrency on the coordinator
            // based on the number of nodes in the cluster
            final int maxConcurrentShardRequests = request.paramAsInt("max_concurrent_shard_requests",
                searchRequest.getMaxConcurrentShardRequests());
            searchRequest.setMaxConcurrentShardRequests(maxConcurrentShardRequests);
        }
        //允许部分搜索结果
        if (request.hasParam("allow_partial_search_results")) {
   
            // only set if we have the parameter passed to override the cluster-level default
            searchRequest.allowPartialSearchResults(request.paramAsBoolean("allow_partial_search_results", null));
        }

        // do not allow 'query_and_fetch' or 'dfs_query_and_fetch' search types
        // from the REST layer. these modes are an internal optimization and should
        // not be specified explicitly by the user.
        //搜索类型,默认query_then_fetch
        String searchType = request.param("search_type");
        //下面两种查询已经被废弃
        if ("query_and_fetch".equals(searchType) ||
                "dfs_query_and_fetch".equals(searchType)) {
   
            throw new IllegalArgumentException("Unsupported search type [" + searchType + "]");
        } else {
   
            searchRequest.searchType(searchType);
        }
        parseSearchSource(searchRequest.source(), request, setSize);
        //查询缓存
        searchRequest.requestCache(request.paramAsBoolean("request_cache", searchRequest.requestCache()));
        //滚动查询
        String scroll = request.param("scroll");
        if (scroll != null) {
   
            searchRequest.scroll(new Scroll(parseTimeValue(scroll, null, "scroll")));
        }
        //type字段已废弃
        if (request.hasParam("type")) {
   
            deprecationLogger.deprecatedAndMaybeLog("search_with_types", TYPES_DEPRECATION_MESSAGE);
            searchRequest.types(Strings.splitStringByCommaToArray(request.param("type")));
        }
        searchRequest.routing(request.param("routing"));
        searchRequest.preference(request.param("preference"));
        searchRequest.indicesOptions(IndicesOptions.fromRequest(request, searchRequest.indicesOptions()));
        searchRequest.setCcsMinimizeRoundtrips(request.paramAsBoolean("ccs_minimize_roundtrips", searchRequest.isCcsMinimizeRoundtrips()));

        checkRestTotalHits(request, searchRequest);
    }

private static void parseSearchSource(final SearchSourceBuilder searchSourceBuilder, RestRequest request, IntConsumer setSize) {
   
        QueryBuilder queryBuilder = RestActions.urlParamsToQueryBuilder(request);
        if (queryBuilder != null) {
   
            searchSourceBuilder.query(queryBuilder);
        }
        //分页查询
        int from = request.paramAsInt("from", -1);
        if (from != -1) {
   
            searchSourceBuilder.from(from);
        }
        int size = request.paramAsInt("size", -1);
        if (size != -1) {
   
            setSize.accept(size);
        }
        //特定文档如何与查询匹配的详细信息和解释
        if (request.hasParam("explain")) {
   
            searchSourceBuilder.explain(request.paramAsBoolean("explain", null));
        }
        //带版本号查询
        if (request.hasParam("version")) {
   
            searchSourceBuilder.version(request.paramAsBoolean("version", null));
        }
        //是否返回seqNo和primaryTerm
        if (request.hasParam("seq_no_primary_term")) {
   
            searchSourceBuilder.seqNoAndPrimaryTerm(request.paramAsBoolean("seq_no_primary_term", null));
        }
        //超时时间
        if (request.hasParam("timeout")) {
   
            searchSourceBuilder.timeout(request.paramAsTime("timeout", null));
        }
        //收集后终止搜索
        if (request.hasParam("terminate_after")) {
   
            int terminateAfter = request.paramAsInt("terminate_after",
                    SearchContext.DEFAULT_TERMINATE_AFTER);
            if (terminateAfter < 0) {
   
                throw new IllegalArgumentException("terminateAfter must be > 0");
            } else if (terminateAfter > 0) {
   
                searchSourceBuilder.terminateAfter(terminateAfter);
            }
        }
        //指示应如何获取存储的字段
        StoredFieldsContext storedFieldsContext =
            StoredFieldsContext.fromRestRequest(SearchSourceBuilder.STORED_FIELDS_FIELD.getPreferredName(), request);
        if (storedFieldsContext != null) {
   
            searchSourceBuilder.storedFields(storedFieldsContext);
        }
        //从doc_value字段查询
        String sDocValueFields = request.param("docvalue_fields");
        if (sDocValueFields != null) {
   
            if (Strings.hasText(sDocValueFields)) {
   
                String[] sFields = Strings.splitStringByCommaToArray(sDocValueFields);
                for (String field : sFields) {
   
                    searchSourceBuilder.docValueField(field, null);
                }
            }
        }
        //从_source获取结果
        FetchSourceContext fetchSourceContext = FetchSourceContext.parseFromRestRequest(request);
        if (fetchSourceContext != null) {
   
            searchSourceBuilder.fetchSource(fetchSourceContext);
        }
        //在排序时应用,并控制是否也会跟踪分数
        if (request.hasParam("track_scores")) {
   
            searchSourceBuilder.trackScores(request.paramAsBoolean("track_scores", false));
        }

        //如果值未设置,则返回应跟踪的总命中数或 null
        if (request.hasParam("track_total_hits")) {
   
            if (Booleans.isBoolean(request.param("track_total_hits"))) {
   
                searchSourceBuilder.trackTotalHits(
                    request.paramAsBoolean("track_total_hits", true)
                );
            } else {
   
                searchSourceBuilder.trackTotalHitsUpTo(
                    request.paramAsInt("track_total_hits", SearchContext.DEFAULT_TRACK_TOTAL_HITS_UP_TO)
                );
            }
        }
        //排序字段
        String sSorts = request.param("sort");
        if (sSorts != null) {
   
            String[] sorts = Strings.splitStringByCommaToArray(sSorts);
            for (String sort : sorts) {
   
                int delimiter = sort.lastIndexOf(":");
                if (delimiter != -1) {
   
                    String sortField = sort.substring(0, delimiter);
                    String reverse = sort.substring(delimiter + 1);
                    if ("asc".equals(reverse)) {
   
                        searchSourceBuilder.sort(sortField, SortOrder.ASC);
                    } else if ("desc".equals(reverse)) {
   
                        searchSourceBuilder
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值