Counting type complexity only once
dragonfriend0013 opened this issue · 4 comments
I have a query
{ inqAcctGeneralInfo { clientId acctId field1 field2 } }
for schema
Query { inqAcctGeneralInfo: AcctGeneralInfo } type AcctGeneralInfo { clientId: Int acctId: String field1: String field2: String }
and i would like to count the type and assign it a complexity of 5, and have it still count its subfields as 1. So my above query would have a total complexity of 9. I am seeing that the estimators are called per field and i am currently getting complexity of 5 (4 returned fields plus 1 for the query itself). is there any way to be able to count the type once in a custom estimator?
Not sure I fully understand the issue here. You could assign the inqAcctGeneralInfo field a complexity of 5 via one of the estimators and the other fields a complexity of 1. That should give you the result of 9.
ok i think i can make that work. in a large schema where the same type is used in multiple places, being able to code for the type would be easier, than coding for each field that references that type. I am using a large federated schema, so having to pull all those fields could take time, vs just coding for the types once.
@dragonfriend0013 You could just create a custom estimator that returns values for specific types and add that to your chain:
import queryComplexity, {
simpleEstimator
} from 'graphql-query-complexity';
const rule = queryComplexity({
// ...
estimators: [
({field}) => {
switch(field.type.name) {
case 'AcctGeneralInfo': return 5;
}
// Typename not defined in here, let next estimator in chain continue calculation
}
// Add more estimators here...
// Fallback
simpleEstimator({
defaultComplexity: 1
})
]
});i wound up creating a class as i do not want to count the type more than once. I am also using a complexity map to store my complexity values.
`
import lodashClonedeep from 'lodash.clonedeep';
import pointsMap from './pointsMap.mjs';
export default class SpecificEstimator {
constructor() {
this.PointsMap = lodashClonedeep(pointsMap);
}
getSpecificComplexity() {
return (args) => {
const type = this.PointsMap[args.type.name];
let points = 0;
if (args.type.name === 'Query'
|| args.type.name === 'Mutation') {
points += args.childComplexity
+ this.PointsMap.defaultPoints;
return points;
if (type) {
if (!type.beenVisited) {
this.PointsMap[args.type.name].beenVisited = true;
points += args.childComplexity
+ (type.complexity || this.PointsMap.defaultComplexity);
}
const field = type[args.field.name];
if (field) {
points += args.childComplexity
+ (type.complexity || this.PointsMap.defaultComplexity);
} else {
points += args.childComplexity
+ this.PointsMap.defaultComplexity;
}
} else {
points += args.childComplexity
+ this.PointsMap.defaultComplexity;
}
return points;
};
}
}
`