Filtering resources by location #285
mrnkr
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Context
My system uses
postgresandtypeorm.I started with an entity with a location field defined as such:
To consume this field, I created a simple class
PointDtowith the same shape as that interface:This was enough for me to consume the point as a GeoJSON feature and store it as a postgis geometry field.
What I needed
I wanted to be able to filter my resources in a way that would let me get those that were within a given GeoJSON polygon feature or close to a point. Let's focus only on the polygon for now.
Here's an example query:
How I achieved it
This took a lot of trial and error. Since I came up with a working solution I want everyone to be able to use it and, hopefully, improve upon it! If you do make it better, please share :D
First, I disabled
readoperations in my generated resolver.Then, I made a custom resolver extending
ReadResolver. My goal here was to change the generated graphql schema so that it would expose my custom filter which I specified as a DTO.This resolver is an exact copy of what
ReadResolvergenerates. Since I wasn't able to change the filter type any other way I redeclared thequeryManymethod with all its decorators and used my customResourceQueryDtoso that my new operators would be recognized by graphql.Let's take a look at my
ResourceQueryDto:At this point, I registered my resolver in my module and was able to send the
locationoperators,withinandnear, in my filters.All I was missing at this point was actually translating the filters provided to the API into sql where clauses. The library does this in the
FilterQueryBuilderclass, which is a public property of theTypeOrmQueryServiceclass.My first attempt was to extend that class and add the logic to process this new condition BUT since it's internal I wanted to avoid that. What I ended up going with was a
Proxy.I implemented my own
ResourceQueryServiceextending the providedTypeOrmQueryServiceand, then, replaced the instance that is generated by the library with a proxy around it, like so:Lastly, I registered the new service in my module and injected it in my custom resolver. After that, my filters became functional.
I think I may have over-engineered this, I'm pretty sure I have, but this was the best I could come up with. If anybody has any ideas as to how I could simplify this, please do share!
Beta Was this translation helpful? Give feedback.
All reactions