@Override
    public Result search(Query query, Execution execution) {
        String error = QueryCanonicalizer.canonicalize(query);
        if (error != null) return new Result(query, ErrorMessage.createIllegalQuery(error));

        query.prepare();

        if (query.getSelect().getGrouping().isEmpty()) return execution.search(query);

        // Convert requests to Vespa style grouping.
        Map<Integer, Grouping> groupingMap = new HashMap<>();
        List<RequestContext> requestContextList = new LinkedList<>();
        for (int i = 0; i < query.getSelect().getGrouping().size(); i++)
            requestContextList.add(convertRequest(query, query.getSelect().getGrouping().get(i), i, groupingMap));

        if (groupingMap.isEmpty()) return execution.search(query);

        // Perform the necessary passes to execute grouping.
        Result result = performSearch(query, execution, groupingMap);

        // Convert Vespa style results to hits.
        HitConverter hitConverter = new HitConverter(this);
        for (RequestContext context : requestContextList) {
            RootGroup group = convertResult(context, groupingMap, hitConverter);
            result.hits().add(group);
        }
        return result;
    }
Constructs a new instance of this searcher with the given component id.

@param componentId the identifier to assign to this searcher
container-search/src/main/java/com/yahoo/search/grouping/vespa/GroupingExecutor.java