@Override
    public Sequence<Result<TopNResultValue>> run(
        Query<Result<TopNResultValue>> input, Map<String, Object> responseContext) {
      if (!(input instanceof TopNQuery)) {
        throw new ISE("Can only handle [%s], got [%s]", TopNQuery.class, input.getClass());
      }

      final TopNQuery query = (TopNQuery) input;
      if (query.getThreshold() > minTopNThreshold) {
        return runner.run(query, responseContext);
      }

      final boolean isBySegment = query.getContextBySegment(false);

      return Sequences.map(
          runner.run(query.withThreshold(minTopNThreshold), responseContext),
          new Function<Result<TopNResultValue>, Result<TopNResultValue>>() {
            @Override
            public Result<TopNResultValue> apply(Result<TopNResultValue> input) {
              if (isBySegment) {
                BySegmentResultValue<Result<TopNResultValue>> value =
                    (BySegmentResultValue<Result<TopNResultValue>>) input.getValue();

                return new Result<TopNResultValue>(
                    input.getTimestamp(),
                    new BySegmentTopNResultValue(
                        Lists.transform(
                            value.getResults(),
                            new Function<Result<TopNResultValue>, Result<TopNResultValue>>() {
                              @Override
                              public Result<TopNResultValue> apply(Result<TopNResultValue> input) {
                                return new Result<>(
                                    input.getTimestamp(),
                                    new TopNResultValue(
                                        Lists.<Object>newArrayList(
                                            Iterables.limit(
                                                input.getValue(), query.getThreshold()))));
                              }
                            }),
                        value.getSegmentId(),
                        value.getInterval()));
              }

              return new Result<>(
                  input.getTimestamp(),
                  new TopNResultValue(
                      Lists.<Object>newArrayList(
                          Iterables.limit(input.getValue(), query.getThreshold()))));
            }
          });
    }
    @Override
    public Sequence<Result<SearchResultValue>> run(
        Query<Result<SearchResultValue>> input, Map<String, Object> responseContext) {
      if (!(input instanceof SearchQuery)) {
        throw new ISE("Can only handle [%s], got [%s]", SearchQuery.class, input.getClass());
      }

      final SearchQuery query = (SearchQuery) input;
      if (query.getLimit() < config.getMaxSearchLimit()) {
        return runner.run(query, responseContext);
      }

      final boolean isBySegment = BaseQuery.getContextBySegment(query, false);

      return Sequences.map(
          runner.run(query.withLimit(config.getMaxSearchLimit()), responseContext),
          new Function<Result<SearchResultValue>, Result<SearchResultValue>>() {
            @Override
            public Result<SearchResultValue> apply(Result<SearchResultValue> input) {
              if (isBySegment) {
                BySegmentSearchResultValue value = (BySegmentSearchResultValue) input.getValue();

                return new Result<SearchResultValue>(
                    input.getTimestamp(),
                    new BySegmentSearchResultValue(
                        Lists.transform(
                            value.getResults(),
                            new Function<Result<SearchResultValue>, Result<SearchResultValue>>() {
                              @Override
                              public Result<SearchResultValue> apply(
                                  @Nullable Result<SearchResultValue> input) {
                                return new Result<SearchResultValue>(
                                    input.getTimestamp(),
                                    new SearchResultValue(
                                        Lists.newArrayList(
                                            Iterables.limit(input.getValue(), query.getLimit()))));
                              }
                            }),
                        value.getSegmentId(),
                        value.getInterval()));
              }

              return new Result<SearchResultValue>(
                  input.getTimestamp(),
                  new SearchResultValue(
                      Lists.<SearchHit>newArrayList(
                          Iterables.limit(input.getValue(), query.getLimit()))));
            }
          });
    }