RJMetrics / sweet-liberty

A library for building database-backed RESTful services using Clojure
Apache License 2.0
104 stars 6 forks source link

Expansion configuration within api #7

Open smahood opened 9 years ago

smahood commented 9 years ago

I love the idea of expansions, and was wondering if there was a way that might make sense to enable an easier configuration of expansions within the same sweet-liberty project.

Here's a example of a simple resource configuration where it might come in handy.

{:countries {:table {:table-name :countries
                     :attributes [:code
                                  :name]
                     :primary-key :code}}

:provinces {:table {:table-name :provinces
                     :attributes [:id
                                  :id_country
                                  :name]
                     :primary-key :id}}

:cities {:table {:table-name :cities
                  :attributes [:id
                               :id_province
                               :name]
                  :primary-key :id}}}

At least from the way my existing databases are set up, this would bring a couple potential benefits

  1. For databases with lots of joins and views, it would remove the need to define the views separately
  2. No need to define service brokers for expansions contained within the same project, which takes away the need to define the path (which may be changing during development)
  3. Queries can be created in honey sql to all hit the DB at the same time rather than having to do 2 separate api calls

It would be pretty easy from my perspective to just add a map to expandable attributes pointing to the table that they expand to, something along the lines of

:cities {:table {:table-name :cities
                  :attributes [:id
                               :id_province {
                                             :expansion {
                                                         :table-name :provinces
                                                         :foreign-key :id}
                               :name]
                  :primary-key :id}}}

Does that seem like it would be at all desirable, or am I just complicating things more than it's worth and we should just rely on service broker expansion for that type of use case?

bpiel commented 9 years ago

This brings a few things to mind.

Regarding executing local expansions using JOIN, instead of a service broker: This idea came up a few times during development of sweet-lib. I think there's good reasons to want this feature, but here's why we didn't do it:

Another consideration, which I hadn't thought of til just now, is that, currently, sweet-lib doesn't know about whether a relationship is -to-many or -to-one. If sweet-lib receives results from a *-to-many JOIN, it would have to do some extra processing to get back to one record per entity. This paragraph is a little abstract -- sorry if I'm not explaining myself well.

None of these are deal breakers, but they add up. Despite all this, I do think the option to use sql JOIN is a reasonable feature to include within the scope of sweet-lib. It's not a priority for my team now though.

Regarding the alternate structure you proposed: I've thought a little about supporting an inline column meta data notation like in your example. That's how I imagined we might support datatypes, should that become important. Adding expansion relationship there as well seems like a reasonable option. For what it's worth, it does seem possible to write something that would accept your format above and manipulate it into what sweet-lib currently expects.

Thanks for your interest! Let me know if there's anything I didn't address (either well, or at all).

smahood commented 9 years ago

I think it makes sense to stick with the service broker approach for the sake of simplicity. Sql joins are enough of a pain to troubleshoot and get working well when writing it by hand and targeting only one type of DB server. I'm not sure if it would be worth taking on the extra troubleshooting and support burden of dealing with joins, especially if there isn't a big need for it for other users. I know I can get by without them, I'm just going to set up my GET configuration to look at existing views and the rest of the REST commands to deal with the individual tables.

I think it might be a better solution to make it easier to use or define expansion within the same project. Working with the idea of expansion meta-data, rather than worry about using it to define joins something like that could be used to define automatic expansion relationships. It's been so easy and quick to get a simple REST API up and running so far, and it would be awesome if expansions were there pretty much for free as well.