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
postgres
andtypeorm
.I started with an entity with a location field defined as such:
To consume this field, I created a simple class
PointDto
with 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
read
operations 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
ReadResolver
generates. Since I wasn't able to change the filter type any other way I redeclared thequeryMany
method with all its decorators and used my customResourceQueryDto
so 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
location
operators,within
andnear
, 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
FilterQueryBuilder
class, which is a public property of theTypeOrmQueryService
class.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
ResourceQueryService
extending the providedTypeOrmQueryService
and, 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