class SearchQueryService {

    /**
     * Logger.
     */
    private static final Logger LOGGER = LogManager.getLogger(SearchQueryService.class);

    /**
     * Searches by Elasticsearch.
     *
     * @param type        the specified document type
     * @param keyword     the specified keyword
     * @param currentPage the specified current page number
     * @param pageSize    the specified page size
     * @return search result, returns {@code null} if not found
     */
    public JSONObject searchElasticsearch(final String type, final String keyword, final int currentPage, final int pageSize) {<FILL_FUNCTION_BODY>}

    /**
     * Searches by Algolia.
     *
     * @param keyword     the specified keyword
     * @param currentPage the specified current page number
     * @param pageSize    the specified page size
     * @return search result, returns {@code null} if not found
     */
    public JSONObject searchAlgolia(final String keyword, final int currentPage, final int pageSize) {
        final int maxRetries = 3;
        int retries = 1;

        final String appId = Symphonys.ALGOLIA_APP_ID;
        final String index = Symphonys.ALGOLIA_INDEX;
        final String key = Symphonys.ALGOLIA_ADMIN_KEY;

        while (retries <= maxRetries) {
            String host = appId + "-" + retries + ".algolianet.com";

            try {
                final JSONObject params = new JSONObject();
                params.put("params", "query=" + URLs.encode(keyword)
                        + "&getRankingInfo=1&facets=*&attributesToRetrieve=*&highlightPreTag=%3Cem%3E"
                        + "&highlightPostTag=%3C%2Fem%3E"
                        + "&facetFilters=%5B%5D&maxValuesPerFacet=100"
                        + "&hitsPerPage=" + pageSize + "&page=" + (currentPage - 1));
                final HttpResponse response = HttpRequest.post("https://" + host + "/1/indexes/" + index + "/query").
                        header("X-Algolia-API-Key", key).
                        header("X-Algolia-Application-Id", appId).bodyText(params.toString()).contentTypeJson().
                        connectionTimeout(5000).timeout(5000).send();
                response.charset("UTF-8");
                final JSONObject ret = new JSONObject(response.bodyText());
                if (200 != response.statusCode()) {
                    LOGGER.warn(ret.toString(4));

                    return null;
                }

                return ret;
            } catch (final Exception e) {
                LOGGER.log(Level.WARN, "Queries failed", e);

                retries++;
                if (retries > maxRetries) {
                    LOGGER.log(Level.ERROR, "Queries failed", e);
                }
            }
        }

        return null;
    }
}

        try {
            final JSONObject reqData = new JSONObject();
            final JSONObject q = new JSONObject();
            final JSONObject and = new JSONObject();
            q.put("and", and);
            final JSONArray query = new JSONArray();
            and.put("query", query);
            final JSONObject or = new JSONObject();
            query.put(or);
            final JSONArray orClause = new JSONArray();
            or.put("or", orClause);

            final JSONObject content = new JSONObject();
            content.put(Article.ARTICLE_CONTENT, keyword);
            final JSONObject matchContent = new JSONObject();
            matchContent.put("match", content);
            orClause.put(matchContent);

            final JSONObject title = new JSONObject();
            title.put(Article.ARTICLE_TITLE, keyword);
            final JSONObject matchTitle = new JSONObject();
            matchTitle.put("match", title);
            orClause.put(matchTitle);

            reqData.put("query", q);
            reqData.put("from", currentPage);
            reqData.put("size", pageSize);
            final JSONArray sort = new JSONArray();
            final JSONObject sortField = new JSONObject();
            sort.put(sortField);
            sortField.put(Article.ARTICLE_CREATE_TIME, "desc");
            sort.put("_score");
            reqData.put("sort", sort);

            final JSONObject highlight = new JSONObject();
            reqData.put("highlight", highlight);
            highlight.put("number_of_fragments", 3);
            highlight.put("fragment_size", 150);
            final JSONObject fields = new JSONObject();
            highlight.put("fields", fields);
            final JSONObject contentField = new JSONObject();
            fields.put(Article.ARTICLE_CONTENT, contentField);

            final JSONArray filter = new JSONArray();
            and.put("filter", filter);
            final JSONObject term = new JSONObject();
            filter.put(term);
            final JSONObject field = new JSONObject();
            term.put("term", field);
            field.put(Article.ARTICLE_STATUS, Article.ARTICLE_STATUS_C_VALID);

            LOGGER.debug(reqData.toString(4));

            final HttpResponse response = HttpRequest.post(Symphonys.ES_SERVER + "/" + SearchMgmtService.ES_INDEX_NAME + "/" + type
                    + "/_search").bodyText(reqData.toString()).contentTypeJson().timeout(5000).send();
            response.charset("UTF-8");
            return new JSONObject(response.bodyText());
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Queries failed", e);

            return null;
        }
    
<no_super_class>