3 ms·
Could one invent an ad-hoc REST API to perform joins, apply parameters and so forth? Of course. That's what people have been doing. That means every solution is
by atombender 8y ago
Could one invent an ad-hoc REST API to perform joins, apply parameters and so forth? Of course. That's what people have been doing. That means every solution is ad-hoc. People get tired of this.
Have you tried any of the GraphQL client tools? You can literally point a client at an arbitrary server and not only see its schema, but also interact with the API. REST doesn't give you that, because the authors of REST neglected to actually specify anything beyond some fuzzy principles.
> ??? The component doesn't know anything, components don't think.
This is being obtuse. You know perfectly well what I meant: That the component localizes the information needed to make an informed request. This is domain knowledge encoded in the component.
This is contrary to how most developers design clients, where they might call an endpoint such as /posts?limit=10, which happens to fetch all attributes, even if the component doesn't actually need all the attributes.
> You've lost me here. The excerpt you've posted looks even worse than SQL.
Before a summary (and, honestly, tone deaf) dismissal such as this, I recommend reading up on it a bit [1], and maybe trying it out. SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular.
For example, a query such as this:
*{
name,
photos->{ url },
friends->{ name }
}
will return something like:
[
{
"name": "Bob",
"photos": [
{"url": "http://..."},
{"url": "http://..."}
],
"friends": [
{"name": "Jane"}
]
},
...
]
The point isn't that you cannot, with a sufficiently complex ORM and enough elbow grease, do that with SQL. It's that it should be unnecessary, because developers shouldn't need to write an entire data layer every time they want to bring an app up. This is part of what GraphQL brings to the table, too.
[1] https://www.sanity.io/docs/data-store/how-queries-work https://www.sanity.io/docs/data-store/how-queries-work
- hardwaresofton 8y agoGraphQL certainly has a cleaner/less involved interface, but it's also less interoperable. My problem with it is that it doesn't offer much value for the amount of effort, and it isn't the paradigm shift it's claiming to be in the first place, it's just being marketed well. HateOAS[0]+Swagger[1]/jsonschema hyperschema[2] is enough to do what GraphQL does. > This is being obtuse. You know perfectly well what I meant: That the component localizes the information needed to make an informed request. This is domain knowledge encoded in the component. > This is contrary to how most developers design clients, where they might call an endpoint such as /posts?limit=10, which happens to fetch all attributes, even if the component doesn't actually need all the attributes. I apologize, that was a terrible way to phrase my objection. But I want to note that basically GraphQL has offered you a way to avoid writing: axios.get("/posts?limit=10&filter[0]=prop&filter[1]=otherProp&fetchEmbeddedEntities[0]=thing") My point was that you can tack on a not-string query API that declaratively builds this without committing to "implementing a GraphQL endpoint" for all your APIs -- the technology is already there, what people are lacking is shared structure. GraphQL does create shared structure, but in an all-or-nothing way and I avoid building with tools that do that. BTW, as far as actual dynamic API recognition goes, the promise of jsonschema + json hyperschema + json LD is much more promising (it's basically equivalent to the semantic web promise) -- GraphQL is a step in the right direction but the lack of interop means we have to step backwards to go in any other direction. Let me put it this way, could you imagine writing a query where you don't know the name of the model on the server side? Like you only know the thing you want (let's say a "vehicle"), and you know the backend has "vehicles" but you don't know what they're called? Being able to do that query is a paradigm shift, and it's possible with the tools I mentioned, though the promise is yet to be realized by and large. > Before a summary (and, honestly, tone deaf) dismissal such as this, I recommend reading up on it a bit [1], and maybe trying it out. SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular. I've tried it -- I'm not impressed, this is the crux of my point and I haven't seen anything yet that can help me change my mind. It is a fact that the chunk of code you posted as a query is a nightmare to look at. Yes, my brain will eventually Despite how people try there aren't many query languages that can match the expressive power of SQL. For all it's warts, it is excellent at what it does. > SQL is great, but it does not handle nested documents/relationships, so you end up with a lot of messy structural mapping between flat relational data and structured data, which is why projects like Rails/ActiveRecord and Hibernate are so popular. This is a wildly inaccurate statement. SQL is for querying relational database systems. Well structured relational data is the most structured data you're ever going to find. ORMs (ActiveRecord/Hibernate) are: - excellent at reducing boilerplate when it's a perfect fit (pro) - often used by people who don't understand the expressive SQL (con) - great at creating N+1 query problems (con) - great at stopping you from using the deeper features of your DB (con) ORMs are easier, that's why they saw widespread use. It's been my experience that people fall out of love with ORMs as they reach their rough edges (which they must have, they are leaky abstractions). I much prefer query builders/generators and in-language level abstractions (methods/functions/etc). > For example, a query such as this: Please stop posting queries, I get the query language, the DSL is fairly easy to understand (this is great for GraphQL). > The point isn't that you cannot, with a sufficiently complex ORM and enough elbow grease, do that with SQL. It's that it should be unnecessary, because developers shouldn't need to write an entire data layer every time they want to bring an app up. This is part of what GraphQL brings to the table, too. I think you've conflated an ORM with a sufficiently capable and metadata-tagged backend. These features aren't ORM level feature necessarily, look at Postgrest's vertical column filtering[3] and embedded entities[4]. Also, my original point was that GraphQL is over-hyped considering that it is not a paradigm shift, and requires you to do a bunch of non-interoperable work aside from REST without much benefit. I'm going to find some time and implement GraphQL automatically (with the help of jsonschema and hyperschema, etc) on top of a regular RESTful endpoint, I'll post it to HN when I do. [0]: https://en.wikipedia.org/wiki/HATEOAS https://en.wikipedia.org/wiki/HATEOAS [1]: https://swagger.io/specification/ https://swagger.io/specification/ [2]: https://datatracker.ietf.org/doc/draft-handrews-json-schema-hyperschema/ https://datatracker.ietf.org/doc/draft-handrews-json-schema-... [3]: https://postgrest.org/en/v5.1/api.html#vertical-filtering-columns https://postgrest.org/en/v5.1/api.html#vertical-filtering-co... [4]: https://postgrest.org/en/v5.1/api.html#resource-embedding https://postgrest.org/en/v5.1/api.html#resource-embedding
- asdfasgasdgasdg 8y ago> GraphQL has offered you a way to avoid writing: > axios.get("/posts?limit=10&filter[0]=prop&filter[1]=otherProp&fetchEmbeddedEntities[0]=thing") Is that right? I've never used GraphQL, but I thought the main advantage was not that the client didn't have to write that, but that the server didn't have to write the handling code for the joins to the embedded entity (to pick one example), or any of the dozens of other possible joins someone might want to do for any given relation.
- camgunz 8y agoGraphQL is more or less a data description language. It describes queries and mutations. There are JS libraries that take a GraphQL query/mutation, convert it into the spec'd JSON payload, send it to the backend (single endpoint), and map the requested fields back into a JS object to be used. This is super nice when paired with React -- it's hard to overstate how nice it is. On the backend, there are libraries that process that JSON payload into whatever your framework wants (dicts in Python, for example). From that decoded payload, you have to figure out what to do. If you're using Django and you get something like {'name': 'Ruth', 'age': 85} to your 'People' query, you need to ask your ORM for People named Ruth who are 85 years old, and return them. It is essentially exactly like REST API design, with a few important differences: - You don't have to worry about irrelevant HTTP stuff. What status code is appropriate? What HTTP action? Isn't this URL a little wrong? All irrelevant. - There is no standard for pagination or ordering. In fairness, REST's answer (do it in query params... just like everything else!) is a little unsatisfying. But REST never made grandiose claims about data description. You go through the whole GraphQL site and it's more or less just an exposition in how great it is to just _describe_ the fields you want to retrieve/change, but nothing about "what if I just want the first 10,000 results?" This is, as you might imagine, an important and common issue. - There is no (meaningful) standard for errors. I think it's a step in the right direction from REST. URL-based APIs really just never earn their keep, HTTP actions are too limiting, versioning weirds everything, query params naturally grow to contain/become their own DSLs. But as far as backend engineering goes, GraphQL really only addresses the problems we didn't really mind (URLs/HTTP actions) anyway. To answer your question directly: the benefit of GraphQL is... 98% realized only by API clients. The backend is still doing everything it used to.
- deorder 8y agoYou can do this with PostgReST as well. Something like: GET /user?select=name,photo(url),friend(name) I do not use PostgReST, but created something similar. When I perform the following 3 individual requests after I performed the above request the results can all be retrieved from cache (at the server and/or client side): GET /user?select=name GET /user/{name}/photo?select=url GET /user/{name}/friend?select=name Even when I do the following (without the photo(url) part) it can now just build it from the cache without hitting the database server: GET /user?select=name,friend(name) That is one of the advantages of using ReST. It allows you to utilize and benefit from already existing proven and well defined infrastructure components (the connectors etc.). GraphQL can be used on top of this as well. I experimented with this once as an alternative to the PostgReST-like syntax.
- hardwaresofton 8y agoSomeone linked to this thing called subZero[0], which seems to be a starter kit that exposes APIs as GraphQL and REST from a Postgres database (it uses postgrest), maybe it's a good example of them working side by side. [0]: http://docs.subzero.cloud/ http://docs.subzero.cloud/