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
-
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