REST API get multiple records using id - rest

We have the records in the below format :
[
{
id: 1,
name : 'Chris',
class : 'x',
year : 3,
},
{
id: 2,
name : 'John',
class : 'y',
year : 4,
}
]
I want to fetch multiple records based on id with a single api call.
This could be achieved either by passing multiple ids in a get call or using a post call to post the list of ids.
Get call with multiple ids
GET https://api.com/school/names?id=1,2,3
Post with multiple ids
POST https://api.com/school/names?action=get
request body :
{
id1: 1,
id2: 2,
id3: 3
}
We don't have issue with the url length as we will not cross the 2048 characters limit.
I see that many public apis use both of the above approaches, I have a feeling that using a POST call to fetch data is against the REST principle.
Could some one suggest what is the best approach for this scenario and the advantage of the approach compared to the other one.

Related

Advice on structuring data for scalability with large number of nested objects

Looking for advice on how best to structure data in MongoDB, particularly for scalability - worried about having an array of potentially thousands of objects within each user object.
I am building a language learning app with a built in flashcard system. I want users to 'unlock' new vocabulary for each level, which automatically gets added to their flashcards, so when you unlock level 4, all the vocabulary attached to level 4 gets added to your flashcards.
For the flashcards themselves, I want a changable 'due date', so that you get prompted to do certain cards at a certain date - if you're familiar with spaced repition, that's the plan. So when you get a card, you can say how well you know it and, for example, if you know it well you won't get it for another week, but if you get it wrong you'll get it again the next day.
I'm using MongoDB for the backend, but am a little unsure about how best to structure my data. Currently, I have two objects: one for the cards, and one for the users.
The cards object looks like this, so there's a nested object for each flashcard, with a unique ID, the level the word appears in, and then the word in both languages.
const CardsList = [
{
id: 1,
level: 1,
gd: "sgìth",
en: "tired",
},
{
id: 2,
level: 2,
gd: "ceist",
en: "question",
},
];
Then each user has an object like the below, with various user data, and a nested array of objects for the cards - with the id of every card they've unlocked, and the date at which that card is next due.
{
id: 1,
name: "gordon",
level: 2,
cards: [
{ id: 1, date: "07/12/2021" },
{ id: 2, date: "09/12/2021" },
],
},
{
id: 2,
name: "mike",
level: 1,
cards: [
{ id: 1, date: "08/12/2021" },
{ id: 2, date: "07/12/2021" },
],
},
This works fine, but I'm a bit concerned about the scalability of it.
The plan is to have about two or three thousand words in total, and so if I had, say, fifty users complete the app, then that would mean fifty user objects, each with as much as three thousand objects in that nested cards array.
Is that going to be a problem? Would it be a problem if I had a thousand (or more) users, instead of 50? Is there a more sensible way of structuring the data that I'm not spotting?

AppSync batch call for nested properties

My backend REST API takes a list of id's and returns a list of, say, Person objects whose id was requested. Each Person has a children property, which is a list of Person.id. A nice family tree.
// GET /id/[1,2]
{
"id": 1,
"name": "Jacob",
"children": [3, 4]
},
{
"id": 2,
"name": "Jack",
"children": [5, 6]
}
Using AppSync to front said API, I have a resolver for children that makes a call to my API using the following template:
#set( $myMap = {
"id" : $context.source.children
} )
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"id": $util.toJson($myMap)
}
}
This works fine, and AppSync nicely "unwraps" the children array with the appropriate Person. The issue is that if a Person has N children, then N calls are made to my backend API if the client requests the children.
Since my API could take all of the children IDs for all N children at once, it would be nice if AppSync had a way to batch those calls, and then somehow untangle the response and put each Person in the right place.
Question
Is there a way to batch all of individual calls for a nested property into a single call per nested level?
Edit
My GraphQL schema for the example above:
type Person {
id: Int
name: String
children: [Person]
}
AppSync supports this type of batching behavior when proxied through AWS Lambda. See https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html and search for "Batching".
With that being said, based on what you have provided, can you not just call your batch API from the Person.children field for example?
You specified that you have an object:
type Person {
id: Int
name: String
childIds: [String]
children: [Person]
}
Can you not just add the field Person.children that calls your batch HTTP endpoint with the list of children?
type Person {
id: Int
name: String
childIds: [String]
# An HTTP resolver that performs a GET to /id/[1,2]
# where [1,2] comes from $ctx.source.childIds
children: [Person]
}
This will perform a single batch call to your HTTP endpoint per person.
AppSync supports this type of batching behavior to an extent when proxied through AWS Lambda. See https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html and search for "Batching".
With that being said, based on what you have provided, can you not just call your batch API from the Person.children field for example?
You specified that you have an object:
type Person {
id: Int
name: String
childIds: [String]
children: [Person]
}
Can you add the field Person.children that calls your batch HTTP endpoint with the list of children provided by the $ctx.source object?
type Person {
id: Int
name: String
childIds: [String]
# An HTTP resolver that performs a GET to /id/[1,2]
# where [1,2] comes from $ctx.source.childIds
children: [Person]
}
This will perform a single batch call to your HTTP endpoint per person.

Web Api and & EF 6

I have three successives calls to the same web service to post some comments.
The structure is : {Doc_No is TEXT, Line_No is NUMBER, Description is TEXT}
Comments_doc = [{
Doc_No: 'xx_01',
Description : 'TOTO_1'
},
{
Doc_No: 'xx_01',
Description : 'TOTO_2'
},
{
Doc_No: 'xx_01',
Description : 'TOTO_3'
}]
$.each(Comments_doc, function(aComment){
$.post(...) //here post aComment
});
The primary keys are : Doc_No and Line_No
Line_No is calculated by the web service, it looks for the last one and add one.
The problem is ; looking for the last record is faster than the insert, so at any given time, I have the same Line_No for two differents records !
How could I avoid this ?
thank you for your help.

Passing discount code in Orders API on Shopify

I have been trying to develop an app that takes an order on Shopify on a different channel. I successfully placed an order through the API but I am not able to include the discount code along with the order. The JSON object for the POST data is as below:
{
order: {
email : request.params.order.email, // string
financial_status : 'pending', // string
send_receipt : true, // boolean
send_fulfillment_receipt : false, // boolean
note : request.params.order.note, // string
discount_codes : [], // supposed to be an array of Object| Problem here,
line_items : request.params.order.line_items, // array
customer : request.params.customer, // JSON object
billing_address : request.params.order.billing_address, // JSON object
shipping_address : request.params.order.shipping_address // JSON object
}
}
According to the documentation, the discount_codes is like this -
Applicable discount codes that can be applied to the order. If no codes exist the value will default to blank. A Discount code will include the following fields:
amount: The amount of the discount.
code: The discount code.
type: The type of discount. Can be one of : "percentage", "shipping", "fixed_amount" (default).
What am I doing wrong? My discount_codes is this
[{amount: 100,code:'WELCOME10',type:'percentage'}]
Has anyone done this before?
According to this response from Shopify what you are trying to do is only possible if you pass the total_discounts field along as well with the total amount of the discount you want to apply.
As you will see in this other answer, any codes you have created through Shopify are not available to use with the API and their usage will not be recorded.
I was trying to use this API in order to test the application of different coupon codes that I was generating, but this does not seem to be possible. Apparently, the API was intended for applying discounts that are custom, not ones that already exist in Shopify. This is a frustrating limitation to me.
I successfully create orders with discounts all the time, without ShopifyPlus as that is irrelevant. The data structure that works for me looks like this:
[ { "code": "Shop By PizzleFuzzle 10%", amount: "10", "type": "percentage" } ]
The discount object is available only for Shopify Plus merchants.
Once you are a Shopify Plus merchant, you will be able to create discount codes like that:
POST /admin/discounts.json
{
"discount": {
"discount_type": "percentage",
"value": "15.0",
"code": "balderdash"
}
}
Please see more detailed documentation in the discount object at Shopify API: https://help.shopify.com/api/reference/discount
You should use the value property name instead of amount property name.
e.g.
{value: 100,code:'WELCOME10',type:'percentage'}
and not
{amount: 100,code:'WELCOME10',type:'percentage'}

Rest API get resource id by field

What is a correct rest way of getting a resource ID by a field, for example a name. Take a look at the following operations:
GET /users/mike-thomas
GET /users/rick-astley
I don't want to use these operations at my API end, instead I want to write an API operation that will get me the ID when submitting a field (name in the case of users) for example:
GET /users/id-by-field
Submitted data:
{
"fullName": "Mike Thomas"
}
Return data:
{
"data": {
"id": "123456789012345678901234"
}
}
What you want is known as an algorithmic URL where the parameters for the algorithm are passed as URL parameters:
GET /users?name="Mike Thomas"
Advantages are that you are using the "root" resource (users) and the search parameters are easily extended without having to change anything in the routing. For example:
GET /users?text="Mike"&year=1962&gender=M
where text would be searched for in more than just the name.
The resultant data would be a list of users and could return more than the identification of those users. Unless fullName uniquely identifies users, that is what you need to allow for anyway. And of course the list could contain a single user if the parameters uniquely identified that user.
{
users: [
{
id: "123456789012345678901234",
fullName: "Mike Thomas",
dateJoined: 19620228
}
, {
id: "234567890123456789012345"
fullName: "Rick Astley",
dateJoined: 19620227
}
]
}