popurelate
Version:
Easily populate and filter documents using data from related collections.
132 lines (131 loc) • 4.96 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.mongoOptimizationHelper = void 0;
const path_1 = require("../path");
const getFieldsOfPipeline = (pipeline, helper) => {
const is = helper.pipelineIs;
if (is.query(pipeline)) {
return getQueryFields(pipeline.query);
}
if (is.sort(pipeline)) {
return getSortFields(pipeline.sort);
}
if (is.project(pipeline)) {
return getProjectFields(pipeline.project);
}
if (is.addFields(pipeline)) {
return getFieldsOfddFields(pipeline.addFields);
}
if (is.populate(pipeline)) {
return getPopulateFields(pipeline);
}
if (pipeline.invisible && pipeline.optimizer && pipeline.hints) {
return {
IAmChangingFields: pipeline.hints.IAmChangingFields || null,
IAmDependedOnFields: pipeline.hints.IAmDependedOnFields || new Set(),
};
}
return {
IAmChangingFields: null,
IAmDependedOnFields: new Set(),
};
};
exports.mongoOptimizationHelper = {
getFieldsOfPipeline,
};
const getDollarSignFields = (basePath, parentPath, query, fieldSet = new Set()) => {
if (typeof query === "string") {
if (query.indexOf("$") === 0) {
fieldSet.add(path_1.normalizeQueryPath(path_1.joinQueryPath(basePath, query.slice(1))));
}
}
else if (Array.isArray(query)) {
for (const elem of query) {
getDollarSignFields(basePath, parentPath, elem, fieldSet);
}
}
else if (typeof query === "object" &&
!!query &&
query.constructor === Object) {
for (const field in query) {
const startsWithDolar = field.indexOf("$") === 0;
const normalized = startsWithDolar ? field.slice(1) : field;
if (!startsWithDolar) {
fieldSet.add(path_1.normalizeQueryPath(path_1.joinQueryPath(basePath, normalized)));
}
const value = query[field];
const newBasePath = field === "$elemMatch" ? parentPath : basePath;
getDollarSignFields(newBasePath, startsWithDolar ? parentPath : path_1.joinQueryPath(parentPath, normalized), value, fieldSet);
}
}
return fieldSet;
};
const getQueryFields = (query) => {
const dependedFields = getDollarSignFields("", "", query);
return {
IAmDependedOnFields: dependedFields,
IAmChangingFields: null,
};
};
const getSortFields = (sort) => getQueryFields(sort);
const getProjectFields = (project) => {
let hasInclusiveProject = false;
const dependedFields = new Set();
for (const field in project) {
const value = project[field];
if ((typeof value === "number" && value !== 0) ||
value === true ||
typeof value === "string") {
hasInclusiveProject = true;
}
}
const projectFields = new Set();
for (const field in project) {
const value = project[field];
projectFields.add(path_1.normalizeQueryPath(field));
if (typeof value === "number" && value !== 0) {
dependedFields.add(path_1.normalizeQueryPath(field));
}
getDollarSignFields("", "", value, dependedFields);
}
return {
IAmDependedOnFields: dependedFields,
IAmChangingFields: hasInclusiveProject
? { isChangingEveryField: true, except: projectFields }
: { isChangingEveryField: false, fields: projectFields },
};
};
const getFieldsOfddFields = (addFields) => {
const changingFields = new Set();
const dependedFields = new Set();
for (const field in addFields) {
const value = addFields[field];
changingFields.add(path_1.normalizeQueryPath(field));
getDollarSignFields("", "", value, dependedFields);
}
return {
IAmDependedOnFields: dependedFields,
IAmChangingFields: { isChangingEveryField: false, fields: changingFields },
};
};
const getPopulateFields = (populate) => {
const changingFields = new Set();
const dependedFields = new Set();
const helper = (pip) => {
if (!pip.populate.alreadyPopulated) {
changingFields.add(path_1.normalizeQueryPath(path_1.joinQueryPath(pip.populate.globalPathPrefix, pip.field)));
dependedFields.add(path_1.normalizeQueryPath(path_1.joinQueryPath(pip.populate.globalPathPrefix, pip.populate.localField)));
}
if (pip.populate.children) {
for (const key in pip.populate.children) {
const child = pip.populate.children[key];
helper(child);
}
}
};
helper(populate);
return {
IAmDependedOnFields: dependedFields,
IAmChangingFields: { isChangingEveryField: false, fields: changingFields },
};
};