revises misc bugs with mongoose query handlers

This commit is contained in:
James
2020-04-05 17:43:43 -04:00
parent 39537da71b
commit f19809bd04
6 changed files with 42 additions and 35 deletions

View File

@@ -3,30 +3,33 @@ const { APIError } = require('../../errors');
const find = async (options) => {
try {
const {
Model,
query,
model,
query = {},
locale,
fallbackLocale,
paginate,
paginate = {},
depth,
} = options;
// await pre find hook here
const mongooseQuery = await Model.buildQuery(query, locale);
const mongooseQuery = await model.buildQuery(query, locale);
const paginateQuery = {
options: {},
...paginate,
};
if (paginate.page) paginateQuery.page = paginate.page;
if (paginate.limit) paginateQuery.limit = paginate.limit;
if (paginate.sort) paginateQuery.sort = paginate.sort;
if (depth) {
paginateQuery.options.autopopulate = {
maxDepth: depth,
};
}
const result = await Model.paginate(mongooseQuery, paginateQuery);
const result = await model.paginate(mongooseQuery, paginateQuery);
// await post find hook here

View File

@@ -13,7 +13,7 @@ const findByID = async (options) => {
try {
// Await pre findOne hook here
const doc = await options.Model.findOne({ _id: options.id }, {}, mongooseOptions);
const doc = await options.model.findOne({ _id: options.id }, {}, mongooseOptions);
if (!doc) {
throw new NotFound();

View File

@@ -4,7 +4,7 @@ const { find } = require('../queries');
const findHandler = async (req, res) => {
try {
const result = await find({
Model: req.Model,
model: req.model,
paginate: {
page: req.query.page,
limit: req.query.limit,

View File

@@ -4,7 +4,7 @@ const formatErrorResponse = require('../../express/responses/formatError');
const findByIDHandler = async (req, res) => {
const options = {
Model: req.model,
model: req.model,
id: req.params.id,
locale: req.locale,
fallback: req.query['fallback-locale'],

View File

@@ -90,7 +90,7 @@ function init() {
resolve: withPolicy(policies.read, async (_, { id }) => {
return findByID({
depth: 0,
Model: collection.model,
model: collection.model,
id,
});
}),
@@ -121,7 +121,7 @@ function init() {
resolve: withPolicy(policies.read, async (_, args) => {
return find({
depth: 0,
Model: collection.model,
model: collection.model,
query: args,
});
}),

View File

@@ -29,39 +29,43 @@ class ParamParser {
// Entry point to the ParamParser class
async parse() {
for (const key of Object.keys(this.rawParams)) {
if (key === 'where') {
// We need to determine if the whereKey is an AND, OR, or a schema path
for (const rawRelationOrPath of Object.keys(this.rawParams.where)) {
const relationOrPath = rawRelationOrPath.toLowerCase();
if (relationOrPath === 'and') {
const andConditions = this.rawParams.where[rawRelationOrPath];
this.query.searchParams.$and = await this.buildAndOrConditions(andConditions);
} else if (relationOrPath === 'or' && Array.isArray(this.rawParams.where[rawRelationOrPath])) {
const orConditions = this.rawParams.where[rawRelationOrPath];
this.query.searchParams.$or = await this.buildAndOrConditions(orConditions);
} else {
// It's a path - and there can be multiple comparisons on a single path.
// For example - title like 'test' and title not equal to 'tester'
// So we need to loop on keys again here to handle each operator independently
const pathOperators = this.rawParams.where[relationOrPath];
if (typeof this.rawParams === 'object') {
for (const key of Object.keys(this.rawParams)) {
if (key === 'where') {
// We need to determine if the whereKey is an AND, OR, or a schema path
for (const rawRelationOrPath of Object.keys(this.rawParams.where)) {
const relationOrPath = rawRelationOrPath.toLowerCase();
if (relationOrPath === 'and') {
const andConditions = this.rawParams.where[rawRelationOrPath];
this.query.searchParams.$and = await this.buildAndOrConditions(andConditions);
} else if (relationOrPath === 'or' && Array.isArray(this.rawParams.where[rawRelationOrPath])) {
const orConditions = this.rawParams.where[rawRelationOrPath];
this.query.searchParams.$or = await this.buildAndOrConditions(orConditions);
} else {
// It's a path - and there can be multiple comparisons on a single path.
// For example - title like 'test' and title not equal to 'tester'
// So we need to loop on keys again here to handle each operator independently
const pathOperators = this.rawParams.where[relationOrPath];
if (typeof pathOperators === 'object') {
for (const operator of Object.keys(pathOperators)) {
if (validOperators.includes(operator)) {
const [searchParamKey, searchParamValue] = await this.buildSearchParam(this.model.schema, relationOrPath, pathOperators[operator], operator);
this.query.searchParams = addSearchParam(searchParamKey, searchParamValue, this.query.searchParams);
if (typeof pathOperators === 'object') {
for (const operator of Object.keys(pathOperators)) {
if (validOperators.includes(operator)) {
const [searchParamKey, searchParamValue] = await this.buildSearchParam(this.model.schema, relationOrPath, pathOperators[operator], operator);
this.query.searchParams = addSearchParam(searchParamKey, searchParamValue, this.query.searchParams);
}
}
}
}
}
} else if (key === 'sort') {
this.query.sort = this.rawParams[key];
}
} else if (key === 'sort') {
this.query.sort = this.rawParams[key];
}
return this.query;
}
return this.query;
return {};
}
async buildAndOrConditions(conditions) {