lib/search.js
function search(q, esClient, options) {
    esClient = toEsClient(esClient);
    options = Object.assign({ from: 0, size: 25, throwOnInvalid: false }, options);

    return pTry(() => parseQuery(q, options))
    .then((params) => {
        if (!params) {
            return { total: 0, results: [] };
        }

        const matchQueries = buildMatchQueries(params);
        const filterQuery = buildFilterQuery(params);
        const scriptScore = buildScriptScore(params);

        // Need to use Promise.resolve because Elasticsearch does not use native Promise
        /* eslint camelcase: 0 */
        return Promise.resolve(esClient.search({
            index: 'npms-current',
            type: 'score',
            body: {
                size: options.size,
                from: options.from,
                query: {
                    function_score: {
                        boost_mode: 'replace',
                        query: {
                            bool: {
                                must: filterQuery.must,
                                must_not: filterQuery.mustNot,
                                should: matchQueries,
                                minimum_should_match: matchQueries.length ? 1 : 0,
                            },
                        },
                        script_score: scriptScore,
                    },
                },
            },
        }))
        .then((res) => ({
            total: res.hits.total,
            results: res.hits.hits.map((hit) => {
                // We can't use _fields in the query because the JSON properties order get messed up,
                // see https://github.com/elastic/elasticsearch/issues/17639
                // So we filter the source fields manually with pick().. this is not ideal since there's payload
                // navigating through the network that we do not use, but it's definitively better than having order messed up
                const result = pick(hit._source, 'package', 'flags', 'score');

                result.searchScore = hit._score;

                return result;
            }),
        }));
    });
}
function search(q, esClient, options) {
    esClient = toEsClient(esClient);
    options = Object.assign({ from: 0, size: 25, throwOnInvalid: false }, options);

    return pTry(() => parseQuery(q, options))
    .then((params) => {
        if (!params) {
            return { total: 0, results: [] };
        }

        const matchQueries = buildMatchQueries(params);
        const filterQuery = buildFilterQuery(params);
        const scriptScore = buildScriptScore(params);

        // Need to use Promise.resolve because Elasticsearch does not use native Promise
        /* eslint camelcase: 0 */
        return Promise.resolve(esClient.search({
            index: 'npms-current',
            type: 'score',
            body: {
                size: options.size,
                from: options.from,
                query: {
                    function_score: {
                        boost_mode: 'replace',
                        query: {
                            bool: {
                                must: filterQuery.must,
                                must_not: filterQuery.mustNot,
                                should: matchQueries,
                                minimum_should_match: matchQueries.length ? 1 : 0,
                            },
                        },
                        script_score: scriptScore,
                    },
                },
            },
        }))
        .then((res) => ({
            total: res.hits.total,
            results: res.hits.hits.map((hit) => {
                // We can't use _fields in the query because the JSON properties order get messed up,
                // see https://github.com/elastic/elasticsearch/issues/17639
                // So we filter the source fields manually with pick().. this is not ideal since there's payload
                // navigating through the network that we do not use, but it's definitively better than having order messed up
                const result = pick(hit._source, 'package', 'flags', 'score');

                result.searchScore = hit._score;

                return result;
            }),
        }));
    });
}
------------------------------------------------------------