uses find instead of findByID in GraphQL relationships to enable further filtering

This commit is contained in:
James
2020-04-09 12:47:16 -04:00
parent 0dc84070c7
commit cf7ddacebf
7 changed files with 277 additions and 254 deletions

View File

@@ -1,4 +1,3 @@
const mongoose = require('mongoose');
const { NotFound } = require('../../errors');
const findByID = async (options) => {
@@ -10,8 +9,6 @@ const findByID = async (options) => {
depth, locale, fallbackLocale, model, id,
} = options;
const hasMultipleIDs = Array.isArray(id);
if (depth && depth !== '0') {
mongooseOptions.options.autopopulate = {
maxDepth: parseInt(depth, 10),
@@ -20,29 +17,12 @@ const findByID = async (options) => {
mongooseOptions.options.autopopulate = false;
}
let result;
try {
// Await pre find hook here
if (hasMultipleIDs) {
result = await model.find({
_id: {
$in: id.map(docId => mongoose.Types.ObjectId(docId)),
},
}, {}, mongooseOptions);
} else {
result = await model.findOne({ _id: id }, {}, mongooseOptions);
}
const result = await model.findOne({ _id: id }, {}, mongooseOptions);
if (!result || (result && result.length === 0)) throw new NotFound();
if (hasMultipleIDs) {
return result.map((doc) => {
if (locale && doc.setLocale) doc.setLocale(locale, fallbackLocale);
return doc.toJSON({ virtuals: true });
});
}
if (!result) throw new NotFound();
if (locale && result.setLocale) {
result.setLocale(locale, fallbackLocale);

View File

@@ -11,6 +11,7 @@ const graphQLHTTP = require('express-graphql');
const getBuildObjectType = require('./schema/getBuildObjectType');
const buildWhereInputType = require('./schema/buildWhereInputType');
const buildLocaleInputType = require('./schema/buildLocaleInputType');
const buildPaginatedListType = require('./schema/buildPaginatedListType');
const buildFallbackLocaleInputType = require('./schema/buildFallbackLocaleInputType');
const formatName = require('./utilities/formatName');
const { getFind, getFindByID } = require('../collections/graphql/resolvers');
@@ -131,24 +132,7 @@ class GraphQL {
};
this.Query.fields[pluralLabel] = {
type: new GraphQLObjectType({
name: pluralLabel,
fields: {
docs: {
type: new GraphQLList(collection.graphQLType),
},
totalDocs: { type: GraphQLInt },
offset: { type: GraphQLInt },
limit: { type: GraphQLInt },
totalPages: { type: GraphQLInt },
page: { type: GraphQLInt },
pagingCounter: { type: GraphQLInt },
hasPrevPage: { type: GraphQLBoolean },
hasNextPage: { type: GraphQLBoolean },
prevPage: { type: GraphQLBoolean },
nextPage: { type: GraphQLBoolean },
},
}),
type: buildPaginatedListType(pluralLabel, collection.graphQLType),
args: {
where: {
type: collection.graphQLWhereInputType,

View File

@@ -0,0 +1,26 @@
const {
GraphQLList, GraphQLObjectType, GraphQLInt, GraphQLBoolean,
} = require('graphql');
const buildPaginatedListType = (name, docType) => {
return new GraphQLObjectType({
name,
fields: {
docs: {
type: new GraphQLList(docType),
},
totalDocs: { type: GraphQLInt },
offset: { type: GraphQLInt },
limit: { type: GraphQLInt },
totalPages: { type: GraphQLInt },
page: { type: GraphQLInt },
pagingCounter: { type: GraphQLInt },
hasPrevPage: { type: GraphQLBoolean },
hasNextPage: { type: GraphQLBoolean },
prevPage: { type: GraphQLBoolean },
nextPage: { type: GraphQLBoolean },
},
});
};
module.exports = buildPaginatedListType;

View File

@@ -14,7 +14,7 @@ const {
const formatName = require('../utilities/formatName');
const combineParentName = require('../utilities/combineParentName');
const withNullableType = require('./withNullableType');
const findByID = require('../../collections/queries/findByID');
const find = require('../../collections/queries/find');
function getBuildObjectType(graphQLContext) {
const buildObjectType = (name, fields, parentName) => {
@@ -111,14 +111,22 @@ function getBuildObjectType(graphQLContext) {
id = relatedDoc.value;
}
const result = await findByID({
const result = await find({
model: graphQLContext.collections[relatedCollectionSlug].model,
id,
query: {
where: {
_id: {
equals: id,
},
},
},
locale,
fallbackLocale,
});
results.push(result);
if (result.docs.length === 1) {
results.push(result.docs[0]);
}
}
}
@@ -131,15 +139,25 @@ function getBuildObjectType(graphQLContext) {
if (id) {
id = id.toString();
const relatedDocument = await findByID({
const relatedDocument = await find({
model: graphQLContext.collections[relatedCollectionSlug].model,
id,
query: {
where: {
_id: {
equals: id,
},
},
},
locale,
fallbackLocale,
});
return relatedDocument;
if (relatedDocument.docs[0]) return relatedDocument.docs[0];
return null;
}
return null;
},
};
},

View File

@@ -11,6 +11,16 @@ function addSearchParam(key, value, searchParams) {
};
}
function convertArrayFromCommaDelineated(input) {
if (Array.isArray(input)) return input;
if (input.indexOf(',') > -1) {
return input.split(',');
}
return [input];
}
class ParamParser {
constructor(model, rawParams, locale) {
this.parse = this.parse.bind(this);
@@ -100,7 +110,12 @@ class ParamParser {
// Checks to see
async buildSearchParam(schema, key, val, operator) {
let schemaObject = schema.obj[key];
const localizedKey = this.getLocalizedKey(key, schemaObject);
let localizedKey = this.getLocalizedKey(key, schemaObject);
if (key === '_id' || key === 'id') {
localizedKey = '_id';
}
if (key.includes('.')) {
const paths = key.split('.');
@@ -171,11 +186,11 @@ class ParamParser {
case 'in':
case 'all':
formattedValue = { [`$${operator}`]: val.split(',') };
formattedValue = { [`$${operator}`]: convertArrayFromCommaDelineated(val) };
break;
case 'not_in':
formattedValue = { $nin: val.split(',') };
formattedValue = { $nin: convertArrayFromCommaDelineated(val) };
break;
case 'not_equals':