@geekbears/gb-mongoose-keywords-plugin
Version:
A Mongoose plugin for keyword generation
108 lines • 4.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeywordsMiddleware = void 0;
const lodash_1 = require("lodash");
const helpers_1 = require("./helpers");
const extraction_1 = require("./helpers/extraction");
/**
* Add keyword generation for a given schema
*
* @description
* Automatically generates keywords from the specified local and virtual paths and persists
* them into a new `__keywords` field.
*
* @usage
* Pass an object with the following options to configure the behavior of keyword generation.
*
* Available options are:
* - `paths`: a collection of the local schema paths to generate keywords from
* - `virtuals`: a map of virtual paths to be populated and generate keywords from
* - `omit`: a collection of words to be omitted from the resulting keywords
*
* @remarks
* Keywords will be generated automatically when creating a new document or updating an existing
* one via `findOneAndUpdate`
*/
const KeywordsMiddleware = function (schema, options) {
const { paths, virtuals, omit } = (0, helpers_1.validateOptions)(schema, options);
/**
* Generate and extract keywords based on the preconfigured schema parameters
* @implementation
*/
schema.method('__generateKeywords', async function () {
try {
const document = this;
const leanDoc = document.toObject({ virtuals: false, getters: false });
const localKeywords = (0, lodash_1.flatten)(paths.map(path => (0, extraction_1.extractKeywordsFromField)(leanDoc[path], omit)));
const populatedKeywords = (0, lodash_1.flatten)(await Promise.all((0, lodash_1.keys)(virtuals).map(async (key) => {
const virtualPaths = virtuals[key];
const populatedDoc = (await document.populate(key)).toObject({ virtuals: true });
return (0, lodash_1.flatten)(virtualPaths.map(path => (0, extraction_1.extractKeywordsFromPopulatedField)(populatedDoc[key], path, omit)));
})));
const keywords = (0, lodash_1.uniq)([...localKeywords, ...populatedKeywords]);
if (options.logging)
console.log(`Generated keywords for ${document.$model.name}:${document._id.toString()}`, keywords);
return keywords;
}
catch (err) {
console.error(`Error generating keywords`);
console.error(err);
}
});
/**
* Generate and save this documents keywords
* @implementation
*/
schema.method('__generateAndSaveKeywords', async function () {
const document = this;
const keywords = await document.__generateKeywords();
document.__keywords = [...keywords];
await document.save();
});
/**
* An array containing this document's generated keywords
* @remarks configure a text index on the field
* @implementation
*/
schema.add({
__keywords: {
type: [String],
index: 'text',
},
});
/**
* Pre-Save document hook
* Generate keywords when a new document is created for this collection
* @remarks requires `onNew` option enabled
*/
schema.pre('save', async function () {
if (!options.onNew)
return;
if (!this.isNew)
return;
this.__keywords = await this.__generateKeywords();
});
/**
* Pre-Update query hook
* Generate keywords when a document in this collection updated
* @remarks requires `onUpdate` option enabled
*/
schema.pre('findOneAndUpdate', { query: true, document: false }, async function () {
if (!options.onUpdate)
return;
const document = await this.model.findOne(this.getQuery());
if ((0, lodash_1.isNil)(document))
return;
this.set({ __keywords: await document.__generateKeywords() });
});
schema.post('findOneAndUpdate', async function (document) {
if (!options.onUpdate)
return;
if ((0, lodash_1.isNil)(document))
return;
const __keywords = await document.__generateKeywords();
await document.updateOne({ __keywords });
});
};
exports.KeywordsMiddleware = KeywordsMiddleware;
//# sourceMappingURL=keywords.plugin.js.map