UNPKG

@conpago/mongo-cursor-pagination

Version:

Make it easy to return cursor-paginated results from a Mongo collection

111 lines 4.03 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const underscore_1 = require("underscore"); const config_1 = __importDefault(require("./config")); const bsonUrlEncoding_1 = require("./utils/bsonUrlEncoding"); /** * Performs a search query on a Mongo collection and pages the results. This is different from * find() in that the results are ordered by their relevancy, and as such, it does not take * a paginatedField parameter. Note that this is less performant than find() because it must * perform the full search on each call to this function. * * @param {Collection} collection A collection object returned from the MongoDB library's. This MUST have a Mongo * $text index on it. * See https://docs.mongodb.com/manual/core/index-text/. * @param {String} searchString String to search on. * @param {QueryParams} params * @param {object} params.query The find query. * @param {Number} params.limit The page size. Must be between 1 and `config.MAX_LIMIT`. * @param {object} params.fields Fields to query in the Mongo object format, e.g. {title :1}. * The default is to query ONLY _id (note this is a difference from `find()`). * @param {String} params.next The value to start querying the page. Defaults to start at the beginning of * the results. */ exports.default = async (collection, searchString, params) => { if (typeof params.limit === "string") params.limit = parseInt(params.limit, 10); if (params.next) params.next = (0, bsonUrlEncoding_1.decode)(params.next); params = (0, underscore_1.defaults)(params, { query: {}, limit: config_1.default.MAX_LIMIT, }); if (params.limit < 1) params.limit = 1; if (params.limit > config_1.default.MAX_LIMIT) params.limit = config_1.default.MAX_LIMIT; // We must perform an aggregate query since Mongo can't query a range when using $text search. const aggregate = [ { $match: (0, underscore_1.extend)({}, params.query, { $text: { $search: searchString, }, }), }, { $project: (0, underscore_1.extend)({}, params.fields, { _id: 1, score: { $meta: "textScore", }, }), }, { $sort: { score: { $meta: "textScore", }, _id: -1, }, }, ]; if (params.next) { aggregate.push({ $match: { $or: [ { score: { $lt: params.next[0], }, }, { score: { $eq: params.next[0], }, _id: { $lt: params.next[1], }, }, ], }, }); } aggregate.push({ $limit: params.limit, }); let response; // Support both the native 'mongodb' driver and 'mongoist'. See: // https://www.npmjs.com/package/mongoist#cursor-operations const aggregateMethod = collection.aggregateAsCursor ? "aggregateAsCursor" : "aggregate"; const results = await collection[aggregateMethod](aggregate).toArray(); const fullPageOfResults = results.length === params.limit; if (fullPageOfResults) { response = { results, next: (0, bsonUrlEncoding_1.encode)([(0, underscore_1.last)(results).score, (0, underscore_1.last)(results)._id]), }; } else { response = { results, }; } return response; }; //# sourceMappingURL=search.js.map