You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Calculate the query complexity based on how nested a field is (depth limitation) #96
So I was trying to see how other calculate their query complexity and ended up in the hygraph website, as you can see in their doc they are saying that how they calculate the query complexity is like this:
Scalar fields: Each scalar field in a query contributes one point to the query complexity.
Relations / Unions: Relations multiply their complexity times the level of nesting in the query.
So I tried to find out how I can do it with this lib but it seems it is not possible with the current API. I also wanna point out that I feel like it is not completely impossible but I kinda have no clue as to how should I go about this: "multiply their complexity times the level of nesting in the query."
Any comment?
Side note: In NestJS we can see the same recommendation about scalar fields, i.e. to add one point to the overall complexity per scalar field (ref).
So my first question now I know that I have access to something called node which in NestJS is part of the type defined for the complexity estimator as you can see it here
But in runtime we have access to it:
This object is the FieldNode. Now I think I just need to look for a way to find the current fields nesting level by using node.
I had some progress, now I know I can calculate field nestedness level using node.loc.source and field.name. Although field.name is not gonna cut it since what if it is nested within nested with the same name:
{
getPosts {
idauthor {
posts {
id
}
}
}
}
I cannot differentiate the first id from the second id but I can use field.astNode.loc.start I guess to do some string interpolation. Although I feel like I am reinventing the wheel, are not I 💦?
So I managed to do it. Here is how I did it: I have a fieldDepth helper function to calculate the depth of each field. Then I mutiply it to a hard coded value for that field and add it to the childComplexity. I am not sure about the math formula since in my test app in my local system when I execute this query it takes 5 seconds to return a response.
He also talks about how he gives complexity of 0 to simple scalar types whereas here hygraph says that scalar fields contributes one point to the overall complexity of a query.
Do you think we should add this to this lib's doc @ivome? TBH I have mixed fillings about it since this is rather implementation details and has nothing to do directly with this lib, but on the other hand I feel a lot of devs who are new to GraphQL will benefit from it since it shows how to calculate the complexity of a query.
BTW I was digging on this topic of depth limitation and I read here that this lib does check the complexity of a query by assigning a number to each field. So when I looked at my own code I realized that most likely I do not need even that lib since I am already calculating the depth of a field and incorporate it to the field's complexity score.
So maybe we can add it to this lib so that people know how they can limit the complexity of a query by its depth + a static score. My current implementation look like this:
import{FieldNode}from'graphql';import{fieldDepthQueryNormalizer}from'./field-depth-query-normalizer.util';/** * @description Calculates the depth of a field */exportfunctionfieldDepth(node: Readonly<FieldNode>){if(!node.loc){throw'EmptyNodeLocation';}if(!node.name.loc){throw'EmptyNodeNameLocation';}constnormalizedSourceBody=fieldDepthQueryNormalizer(node.loc.source.body,);return(normalizedSourceBody.slice(0,node.name.loc.start).split('{').length-2);}
And finally the field-depth-query-normalizer.util.ts:
import{DefinitionNode,DocumentNode,Kind,parse,print,}from'graphql';/** * @description Strips the query from fragments */exportfunctionfieldDepthQueryNormalizer(query: Readonly<string>,): string{constast=parse(query);constdefinitionNodes: DefinitionNode[]=[];constdefinitions=(astasDocumentNode).definitions;for(constdefinitionofdefinitions){if(definition.kind!==Kind.OPERATION_DEFINITION){continue;}definitionNodes.push(definition);}returndefinitionNodes.map((definitionNode)=>print(definitionNode)).join(' ');}
changed the title [-]Calculate the query complexity based on how nested a field is[/-][+]Calculate the query complexity based on how nested a field is (depth limitation)[/+]on Dec 24, 2024
Activity
kasir-barati commentedon Dec 19, 2024
BTW I forked this repo since I thought I might find some kind of clue there and open a PR, but I also love to hear what you know about this.
kasir-barati commentedon Dec 19, 2024
So my first question now I know that I have access to something called
nodewhich in NestJS is part of the type defined for the complexity estimator as you can see it hereBut in runtime we have access to it:
This object is the
FieldNode. Now I think I just need to look for a way to find the current fields nesting level by usingnode.kasir-barati commentedon Dec 19, 2024
I had some progress, now I know I can calculate field nestedness level using
node.loc.sourceandfield.name. Althoughfield.nameis not gonna cut it since what if it is nested within nested with the same name:{ getPosts { id author { posts { id } } } }I cannot differentiate the first
idfrom the secondidbut I can usefield.astNode.loc.startI guess to do some string interpolation. Although I feel like I am reinventing the wheel, are not I 💦?kasir-barati commentedon Dec 20, 2024
Had some progress: https://stackoverflow.com/q/79297272/8784518
kasir-barati commentedon Dec 20, 2024
So I managed to do it. Here is how I did it: I have a
fieldDepthhelper function to calculate the depth of each field. Then I mutiply it to a hard coded value for that field and add it to thechildComplexity. I am not sure about the math formula since in my test app in my local system when I execute this query it takes 5 seconds to return a response.Of course I am not using dataloader and I have the issue of N+1. But if you're interested in it check out my code here.
Off-topic:
Any comment on these?
kasir-barati commentedon Dec 24, 2024
BTW I was digging on this topic of depth limitation and I read here that this lib does check the complexity of a query by assigning a number to each field. So when I looked at my own code I realized that most likely I do not need even that lib since I am already calculating the depth of a field and incorporate it to the field's complexity score.
So maybe we can add it to this lib so that people know how they can limit the complexity of a query by its depth + a static score. My current implementation look like this:
And here is the code for
field-depth.ts:And finally the
field-depth-query-normalizer.util.ts:[-]Calculate the query complexity based on how nested a field is[/-][+]Calculate the query complexity based on how nested a field is (depth limitation)[/+]