Can prisma achieve the same things as graphql? - sql

I'm having a hard time understanding what graphql can achieve on top of prisma besides having a singular endpoint.
I've been hearing that the main selling point of graphql is the fact that you are able to query for the specific fields you want to receive, but can't that also be achieved with prisma using the "select" property?
const users = await user.findMany({
select: {
email: true,
},
});
Thank you for your answers!

I understand your confusion. I'll try to make the difference between Prisma and GraphQL clearer for you.
Prisma
Prisma is an ORM like tool. This means that it helps you search for data in your database. Helps you create queries, join data and etc. Prisma is a tool that lives in your back-end (usually) and helps you find the data that you will send to your front-end or mobile application.
GraphQL
GraphQL is a way to communicate with your back-end. So let's say that you want get the name of a user based on its id. On a REST API (that is the more common way) you would send a GET request to the server, and it would respond with a JSON with all of the data for this user.
// Imagine this is your request to the server
await api.get(http://myserver.com/user/1)
// Imagine this is your JSON response
{
name: "Person",
age: 24,
address: "Avenue Street, number 7",
...
}
You see that even though you just wanted the name of the user you got all of the data, when using a REST API. But with GraphQL that is not the case. You can request for only the data that you want.
// Your request to the server would look like this
{
GetUserById(1) {
name
}
}
// In the response you would be getting a JSON with only the data that you requested
{
name: "Person"
}
That is what GraphQL is used for, requesting specific data to your back-end and receiving only what you need. In both cases, REST API and GraphQL, you can use Prisma. It will help you search in your database for the data that was requested.
If you want to know more about Prisma you can check their website where you will find more about how it works and how to use it.
If you want to know more about GraphQL you can check their FAQ page
You can also learn how to use Prisma and GraphQL together

Related

Accessing site options via a REST API

I'm building a REST API powered SPA application and I'm trying to decide on the best way to deliver "global options" via the API. By global options I mean an assortment of random fields that relate to the application as a whole rather than being associated with one specific model, for example brand logos and contact details that need to be accessible from multiple locations within the app.
Something like Wordpress would store these in an options table and access them via a php function using the option name, however since this is a REST API I'm not sure how I would go about accessing/updating multiple options without making lots of requests for each one.
I know a lot of projects just use a json file to store this data, but it specifcally needs to be editable via a CMS and served via the API. The following are two methods that have come to mind, but none of them feel like complete solutions:
1: An options table with one generic endpoint that takes a query string specifying which fields you want to access. This works for getting data, however updating data seems to get a bit messy and the only way I can think to do this is by sending an object of key/values pairs to bulk create or update the options:
GET: example.com/api/options?pick=logo,contact_phone,contact_email
POST: example.com/api/options
{
contact_email: "info#example.com",
contact_address: "123 Test St"
}
PUT: example.com/api/options
{
contact_email: "info#example.com",
contact_address: "123 Test St"
}
2: Breaking fields into groups and storing them as a json field in a "pages" table, this solves the creating and updating issues but breaks down when you have fields are used in multiple locations, and they aren't really pages so it's not very REST like.
GET: example.com/api/pages/contact
POST: example.com/api/pages
{
name: "contact",
values: {
email: "info#example.com",
address: "123 Test St",
}
}
PUT: example.com/api/pages/contact
{
values: {
email: "info#example.com",
address: "123 Test St",
}
}
I also need to take into account the issue of access permissions, for example the logo field would be accessible to the public, but the user support contact number would only be accessible to logged in users. With the first example you could have an extra permission column for each option, but this wouldn't work for the second option.
I've been googling but have failed to find any good information about this topic as REST schemas/documention generally only deal with concreate entities, so any insight into how this is achieved in real world applciations would be great!
Cheers,
Cam

How do I specify specific data from an API?

I am attempting to extract specific data from the Steam API so far I have been able to filter the results, here is an example;
https://store.steampowered.com/api/appdetails?appids=218620&filters=metacritic
Which gives me;
{"218620":
{"success":true,
"data":
{"metacritic":
{"score":79,"url":"https:\/\/www.metacritic.com\/game\/pc\/payday-2?ftag=MCD-06-10aaa1f"}
}
}
}
However, what I want is just the numerical score, so in this instance, it would just display '79'.
I am presenting the data using an iframe which is why it needs to call the specific value. If anyone has any suggestions about how I can do this or maybe offer up an alternative way to parse the data.
My coding skills are limited so this might seem like a basic question or a rather rudimentary way to extract the data so apologies in advance. I am also adding the code to Shopify which is PHP based if that helps.
I know https://steamspy.com/api.php have their own API which offers similar data would it be easier to collect it from there instead of directly from the Steam Store?
The data you get is in JSON format. JSON is designed for easy data access.
You did not specify your programming language and I have no experience with shopify. So here it is in Javascript. Try this JSFiddle.
const jsonObject = {
"218620":
{"success":true,
"data":
{"metacritic":
{"score":79,"url":"https:\/\/www.metacritic.com\/game\/pc\/payday-2?ftag=MCD-06-10aaa1f"}
}
}
};
const metacriticScore = jsonObject["218620"].data.metacritic.score;
console.log(metacriticScore);

RESTful way of referencing other resources in the request body

Let's assume that I have a resource called group with the following representation:
{
"id": 1,
"name": "Superheroes"
"_links": {
"self": {
"href": "http://my.api.com/groups/1"
}
}
}
Now let's say I want to create a new person instance by POSTing to /persons/1. Which of the following should I use for the request body:
Using ID
{
"name": "Batman",
"groupId": 1
}
Using link
{
"name": "Batman",
"group": "http://my.api.com/groups/1"
}
With the first method I access the id directly either to look up the related resource or eventually store the id in the database, when I persist the person instance. But with the other method, I either have to extract the id from the URI or, follow the link to load the related resource, and then find out its id. I really don't want to store the URI in the database.
With the latter option, seeing that the server controls the structure of the URI, is it fine for me to parse the id out of the link? Following the link back to the server itself seems odd, seeing that at this point we already have access to the information directly (we just need the id).
So to sum up, which of these options is best?
Use the id directly.
Use the link, but parse out the id.
Use the link, but access the link to get the resource instance, and then get the id.
TL;DR: Use simple ids.
More detailed explanation:
A straightforward approach is to create a person by POSTing to /groups/1/persons with a payload {"name": "Batman"}.
However, while such approach works for simple cases, the situation gets complicated if there are 2 resources that need to be referenced. Let's assume that a person also needs to belong to exactly one company:
GET /persons/1
{
"name": "Batman",
"group": 1, // Superheros, available at /groups/1
"company": 5 // Wayne Enterprises, available at /companies/5
}
Since there is no relationship between companies and groups, it is not semantically correct to create a person via POSTing to /groups/1/companies/5/persons or to /companies/5/groups/1/persons.
So let's assume you want to create a person with a request looking like this:
POST /persons
{
"name": "Batman"
"group": ???, // <--- What to put here?
"company": ??? // <--- What to put here?
}
Which brings us to the answer to your question:
Ease of use. Your API should be primarily designed for the ease of use. This is especially true, if you design a public API. Therefore, Option 2 (Use the link, but parse out the id) is out, since it imposes additional work for clients of your API.
Constructing search queries. If you want to be able to query persons which belong to the company 10 and the group 42, simple ids lead to more readable and less error-prone urls. Which of the following do you consider more readable?
URL with a simple id:
GET /groups/42?company=10
or URL with a url-encoded link:
GET /groups/42?company=http%3A%2F%2Fmy.api.com%2Fcompanies%2F10
I wouldn't underestimate the point of readability. How many times do you need to debug your API in various curls, logs, postmans, etc.
Development Links need to be parsed in the backend, while simple ids can be used directly. It's not about performance, but rather about additional work/tests you have to put in.
Endpoint maintenance. Imagine that your API endpoint evolves. You decide one day to switch to https or to include versioning in the url. This might break API clients, if they for some reason rely on structure of the links. Also, you might want to checkout if link parsing on your backend is done properly.
Argumentum ab auctoritate I know this is not a proper argument, but if you checkout APIs of large players, e.g. Twitter, Github or Stripe, they all use simple ids.
HATEOAS. One common argument in favour of links is that it is aligned with HATEOAS. However, as far as I know, this relates to additional links in API responses rather than using links in payloads of POST requests.
All in all, I would go for simple ids, since I haven't yet heard a compelling argument favouring links, which would beat the aforementioned.
You are missing two important things here.
You need a standard way to describe forms in the response, in this case your POST form.
The information about the group ids / uris, or how to get them has to be described in the form in a standard way.
For example a HTML FORM with a SELECT INPUT would be RESTful. The closest thing we got in json to do the same is json-ld and hydra. But if you are obsessed with hal, then use hyperagent forms or something like that. It will never be a standard, but if compatibility is not an issue, then it is good enough.
To answer your question, you should use the id, because the server knows how to interpret it. The client needs the resource identifiers, the server needs it only in the uri part of the request, not in the body.
From my experience, it is always best to go with the simplest solution for making requests.
The process of generating a new url and parsing it seems excessive to get a resource, whereas sending the id of the item you want seems much simpler.
Thus, I would send a request in the form:
{
"name": "Batman",
"group": 1
}

Some general restful api design questions

A few general design questions:
Give the example here:
https://developers.google.com/+/api/latest/activities/list#nextPageToken
Why would the server return a token to retreive the next paginated result? Doesn't this break the idea of being stateless?
Why not just pass a MySQL like LIMIT name=value as the parameters? The server now has to return the number of pages I suppose...what am I missing?
I read many but this one was of interest:
REST Web Services API Design
The second reply, offers the following examples.
GET http://api.domain.com/user/<id>
GET http://api.domain.com/users
PUT http://api.domain.com/user/<id>
POST http://api.domain.com/users
DELETE http://api.domain.com/user/<id>
Makes sense but why are there two plural resources? Could one not assume that if "user" is queried and was NULL or not provided that "all" was intended? Likewise for POST? If plural is for improved readability - why is there not a "users" resource for DELETE?
Ultimately, I understand REST to mean...representation of a single resource - using HTTP verbs (GET, PUT, POST, DELETE) to essentially manage that resource - similar to CRUD.
EDIT | Lastly I also wanted to ask why Google API sends the API version in the URI instead of using HTTP headers? Is there a reason? For backwards compat with older clients?
Comments?
Why would the server return a token to retrieve the next paginated result? Doesn't this break the idea of being stateless?
Using this kind of mechanism for paginated result sets is completely standard and does not break the idea of being stateless. Consider the following example.
Suppose GET /users?after=<after> (where after is optional) is supposed to return the list of all users in a paginated fashion, say <= 4 per page.
The first request a client makes is GET /users with a response that might look like the following (formatted as JSON).
{
"users": [ "alex", "bob", "carter", "dan" ]
"more_after": "dan"
}
In this example, the more_after property designates there may be more users left in the user list. So the client then requests GET /users?after=dan and gets a second response that looks like the following.
{
"users": [ "edward", "frank" ]
}
The absence of the more_after property designates that this is the last page of users.
Now the question is: was the "dan" token used as the page separator something that breaks the "statelessness" property we want? Clearly the answer is no. The server doesn't have to remember anything between the two GET requests. There's no concept of a session. Any state that needs to persist between the two GET requests exists only client-side - that's the important distinction. It's completely acceptable - and often required - to have the client persist state between calls to the service.

Retrieve the list of friends that did a custom action on a custom object in open graph 2

I would like to do something like facepile using the graph api with open graph 2 actions : from a custom object and a custom object, give me the friends (using my facebook application) that did this action on this object.
The problem is that using FQL, I cannot query custom objects and actions. Using the graph API, I cannot find a way to intersect the list of my friends with the object I'm interested in.
The best I could do was the following using the batch mode of the graph API :
batch=[
// First we get the list of friends that are using my facebook application
{ "method": "GET", "relative_url": "fql?q=SELECT+uid+FROM+user+WHERE+uid+IN+(SELECT+uid1+FROM+friend+WHERE+uid2=me())+AND+is_app_user=1+LIMIT+0,49", "name": "friends"},
// Then query each friend to get the list of objects that went through my namespace:testaction
{ "method": "GET", "relative_url": "{result=friends:$.data.0.uid}/namespace:testaction" },
{ "method": "GET", "relative_url": "{result=friends:$.data.1.uid}/namespace:testaction" },
...
{ "method": "GET", "relative_url": "{result=friends:$.data.49.uid}/namespace:testaction" }
]
It's quite inefficient and does not fully resolve my issue since :
I still have to filter the results to get only the one that matches
the object I want
If there is a large number of objects in namespace:testaction, I have to go through paging, doing more queries (I try to minimize the number of queries)
Do you see a better way to do this ?
This probably isn't exactly what you're looking for, but given the fact that facebook (AFAIK) doesn't provide (and will probably never provide) the ability to do this. I think you should simply store the information yourself and then query the data from your own database. It would be like what you're doing in your question, but you can optimize it since it's your database.
I'm sure you thought about this already, but someone had to say it.
It's now possible to do this with one Graph API request:
GET https://graph.facebook.com/me/friends?limit=50&fields=name,namespace:testaction.limit(100)
see field expansion and updates to the graph API.
If the answer derickito gave is not enough, you should explore getting your app on the Facebook white-list (aka become a partner) to get at some the private Graph API where this functionality might exist, but is not available for "normal" application that are stuck using the public Graph API.