RESTfully searching for records associated with an account - javascript

My API has two records: Car and Account. An Account may have many associated Car records.
I have REST routes for updating deleting creating a car record.
Normally, a GET route for call for all cars would look like this: /car
A route for a specific car would be /car/:id the :id being from the Car.
How would I set up a REST route to get call cars by account ID? Would I have to do something like account/:id/car?

You can do it hierarchical with URI path or use querystring. The URI RFC covers this I think.
/cars?account=123
/accounts/123/cars
As of REST you can return a hyperlink with the upper, something like
{
"operation": "ListCarsAssociatedWithAccount(accountId)",
"method": "POST",
"URI": "/accounts/{accountId}/cars",
"params": {"accountId": {"type":"AccountId"}}
}
The REST client should know only about how to call the ListCarsAssociatedWithAccount(accountId) and the URI and body templates can be filled with the params.
With this approach you can even describe the body of the POST request and the expected response if you want to and automate it further:
{
"operation": "ListCarsAssociatedWithAccount(accountId, x)",
"params": {
"accountId": {"type": "AccountId"},
"x": {"type": "Number"}
},
"method": "POST",
"URI": "/accounts/{accountId}/cars",
"body": {
"q": {
"w": {"param": "x"}
}
},
"returns": {
"type":"CarList",
}
}
ListCarsAssociatedWithAccount(123, 5)
->
POST "/accounts/123/cars"
{
"q": {
"w": 5
}
}
200 OK
{
operations: [...],
values: [
{"carId": 34, operations: [...]},
{"carId": 3, ...},
{"carId": 4, ...},
...
]
}
->
var cl = new CarList();
cl.support(o.operations);
var item1 = new Car("carId": o.values[0].carId);
item1.support(o.values[0].operations);
cl.add(item1)
...
return cl;
Something similar (but a lot more complex) is used in the Hydra framework. http://www.hydra-cg.com/

The endpoints are consider flexible and cheap to add (and modify while preserving backward compatibility). But normally something like this:
GET/UPDATE/DELETE: accounts/:id/cars/:carid
GET(search)/CREATE: accounts/:id/cars/
and you could also get the same information from:
GET/UPDATE/DELETE: cars/:carid
GET(search)/CREATE: cars/
Note that on the backend, you should be using the same logic for both endpoints though (reusing code here between the endpoints). The idea of the first set of endpoints is that you can drill into specific elements in a logical/hierarchical manner. So if you needed some sub element of cars for a specific account:
GET/UPDATE/DELETE: accounts/:id/cars/:carid/wheels
That allows maximal use/reuse of data without the need to constantly add filters based on account/car in the various endpoints.
NOTE: normally the endpoints would be pluralized so that you can do searches from the same endpoint, so `GET /accounts' could include search parameters to gather result sets.

Related

API accessing certain values from data with JavaScript

I have the following API Data:
[
{
"symbol": "AAPL",
"name": "Apple Inc.",
"price": 144.98,
"changesPercentage": -1.22,
"change": -1.79,
"dayLow": 142.54,
"dayHigh": 146.96,
"yearHigh": 150,
"yearLow": 93.7125,
"marketCap": 2419368132608,
"priceAvg50": 138.45343,
"priceAvg200": 131.05212,
"volume": 113982837,
"avgVolume": 85057328,
"exchange": "NASDAQ",
"open": 144.81,
"previousClose": 146.77,
"eps": 4.449,
"pe": 32.587097,
"earningsAnnouncement": "2021-07-27T16:30:00.000+0000",
"sharesOutstanding": 16687599204,
"timestamp": 1627504655
}
]
And here is my code with a fake API code:
var $stocks = $('#stocks');
$.ajax({
type: 'GET',
url: 'https://financialmodelingprep.com/api/v3/quote/AAPL?apikey=c0dabd2d8a382584d2144bdefde830f2',
success: function (percent) {
$.each(percent, function (i, item) {
$stocks.append(percent.changesPercentage);
})
}
});
All I would like to do is get the changesPercentage and display it on my webpage with HTML and CSS. I will have various data from different companies, so a versatile solution would be very helpful.
You're trying to get changesPercentage from percent, which is the entire response array. So that property would be undefined.
Instead, it looks like you want to get that value from each element in the array. For that you would use the item parameter of the callback function in $.each:
$stocks.append(item.changesPercentage);
Alternatively, you could also use the i parameter as an indexer for the original array:
$stocks.append(percent[i].changesPercentage);
As an aside, this appears to be a result of using poor variable names which confuse yourself. percent is a misleading name for an array of objects. Something like results would be better, or perhaps the plural form of whatever noun actually describes what these API results are.
Names are important in code. They carry information about what that thing is and how it can be used.

Searching for multiple facetsValues in Algolia

I have an array of Facet Values that I need to gather from an Algolia Indices.
For example, these are: "Beds", "Occupancy". and "Floor".
At the moment, i've got the below code which will go to my Algolia Table, grab me all of the possible values for each of the above but I have to do a query into Algolia for each one. This results in 3 network calls to Algolia.
index.searchForFacetValues(
{
facetName: val,
facetQuery: "",
maxFacetHits: 100,
query: "2019"
},
function(err, content) {
return content
})
Is there a way that I can get all the facet values for "Beds", "Occupancy". and "Floor" in a single query resulting in only one network call?
Also, i'm using https://www.algolia.com/doc/api-client/getting-started/install/javascript/
You can use an empty search and specify which facets you want to receive values for:
client.search({
query: '',
facets: ['Beds', 'Occupancy', 'Floor'],
attributesToRetrieve: [], // a little optimisation for response transfer speed
});
The response will contain something like this:
{
"facets": {
"Beds": {
"2": 1245,
"4": 893,
...
},
"Floor": {
...
},
...
}
}
So the first level of keys in facets are your facet names, and within each nested facet object you have one key/value per facet value/hits count.
If you don't know in advance the list of facet names you want to get, use facets: '*' in your query parameters.

Retrieving only the parent elements from firebase : Angularfire

The image shows the structure of my database.
I want to print 1, 2 ... (so on) i.e. the parent element names alone. But couldn't understand how to do that.
The Firebase Database is essentially one JSON object.
This object is in a tree structure. If you read from one location in the tree, you'll get each piece of data underneath it.
Take a look at this sample database.
{
"items": {
"1": {
"title": "Hi"
},
"2": {
"title": "Bye"
}
}
}
There is no way with the JavaScript SDK or AngularFire, to only read the parent keys of 1 and 2 under "items".
If you only want to read the parent keys, you'll need to create an index for them in the Firebase database.
{
"items": {
"1": {
"title": "Hi"
},
"2": {
"title": "Bye"
}
},
"itemKeys": {
"1": "Hi",
"2": "Bye"
}
}
Now you can create a reference at the itemKeys location and pass that to a $firebaseArray() or $firebaseObject().
var ref = new Firebase('<my-firebase-app>.firebaseio.com/itemKeys');
var syncArray = $firebaseArray(ref);
If you're concerned with keeping two separate data structures consistent, check out the client-side fan-out feature.
shallow=true
If you are using REST API add this to the end of your request url. Like this
https://docs-examples.firebaseio.com/rest/retrieving-data.json?shallow=true

backbone parse model with JSON from server

I am working with backbone at the moment, I run a fetch on a new model, and get a response from the server, the model I am fetching should have other models and collections within it, the JSON returned supports this and it looks something like this,
{
"id" : 230,
"name" : "A project name",
"briefversion":{
"id":199,
"project_id":230,
"version_number":1,
"name":"Version 1",
"created_at":"2015-05-14 10:22:29",
"updated_at":"2015-05-14 10:22:29",
"briefversionsections":[{
"id":947,
"briefversion_id":199,
"position":1,
"name":"Overview",
"content":"<p>A general description of the project and some background information, also worth including some context, where is the work going to be used? Billboards, online, showroom etc</p><div><img src="//www.sketchup.com/images/case_study/architecture/robertson_walsh_3.jpg"/></div>",
"created_at":"2015-05-14 10:22:29",
"updated_at":"2015-05-14 10:22:29",
"briefsectonattachments":{}
}, {
"id":948,
"briefversion_id":199,
"position":2,
"name":"Scope of work",
"content":"<p>A list of the deliverables, e.g.</p><ul><li>An exterior view</li><li>An interior view</li><li>An animation</li><li>A website</li></ul>",
"created_at":"2015-05-14 10:22:29",
"updated_at":"2015-05-14 10:22:29",
"briefsectonattachments":{}
},{
"id":949,
"briefversion_id":199,
"position":3,
"name":"Target market",
"content":"<p>ASCribe who the work is to appeal to, what are the demographics and end user types.</p>",
"created_at":"2015-05-14 10:22:29",
"updated_at":"2015-05-14 10:22:29",
"briefsectonattachments":{
}
}]
},
"organisations":{
"id":55,
"name":"Jaguar",
"uri_hash":"jaguar",
"slug":"S336e056",
"information":"",
"type":"organisation",
"currency":"USD",
"notifications":"0",
"add_all":"0",
"created_at":"-0001-11-30 00:00:00",
"updated_at":"2015-05-20 09:16:21",
"users":[
{
"id":111,
"email":"xxxxxxxx#gmail.com",
"first_name":"Matty",
"last_name":"Brook",
"display_name":"mattybrook",
"initials":"MB",
"remember_me":null,
"active":"1",
"invite_code":null,
"forgotten_code":null,
"cost_visible":0,
"login_type":"normal",
"api_token":null,
"created_at":"2015-03-16 15:49:58",
"updated_at":"2015-05-15 13:12:45",
"deleted_at":null,
"pivot":{
"organisation_id":55,
"user_id":111,
"is_admin":"0"
}
}
}
So after the fetch, how can I make sure that briefversion becomes a model and within that briefversionsections within that becomes a collection, similarly how do I make sure that the users attribute of the organisation object also become a collection?
You will need to override parse to handle getting the JSON from your server in the right format. Once that's done you can then instantiate your collections for some of the properties in the initialize method.
For example
initialize: function () {
this.briefversionsections = new Backbone.Collection(this.briefversionsections);
this.users = new Backbone.Collection(this.users);
},
parse: function (response, options) {
var myModel = response.briefversion;
myModel.users= response.organisations.users
return myModel;
}

AngularJS/Restangular indexed JSON data extraction

I've got and app that takes quote input (purity, weight, total), and it pushes to $scope.quote:
// Controller action //
$scope.quote.push({
total: ((($scope.karat * $scope.spot) * $scope.percentage) / 20) * $scope.estimatedWeight,
karat: $scope.karat * 100,
description: $scope.description,
actualWeight: $scope.actualWeight,
estimatedWeight: $scope.estimatedWeight,
percent: $scope.percentage * 100,
spot: $scope.spot
})
and
// Factory //
app.factory('quoteFactory', function() {
var quote = [];
var factory = {};
factory.getQuote = function () {
return quote;
};
return factory;
})
and the post/save upon quote completion
$scope.save = function() {
var now = $scope.getDate();
$scope.quote.push({
createdOn: $scope.getDate()
})
Restangular.all('quote').post($scope.quote).then(function(quote){
$location.path('#/scrap')
});
};
When trying to access the quote JSON for list or edit I can't access all the information needed because of the JSON structure.
{
"0": {
"total": 401.79040000000003,
"karat": 74,
"description": "Rings",
"actualWeight": 12,
"estimatedWeight": 11,
"percent": 80,
"spot": 1234
},
"1": {
"total": 560.7296,
"karat": 56.8,
"description": "Test",
"actualWeight": 22,
"estimatedWeight": 20,
"percent": 80,
"spot": 1234
},
"2": {
"total": 48.5625,
"karat": 92.5,
"description": "Testing",
"actualWeight": 80,
"estimatedWeight": 75,
"percent": 70,
"spot": 20
},
"3": {
"createdOn": "2013-11-26T21:26:42.253Z"
},
"_id": {
"$oid": "52951213e4b05f03172f14e7"
}
}
Each index represents a line item of the quote and the createdOn info. What I'm trying to figure out is if there is a way to be able to access all the line item information without having to call each individual index?
I've looked into some lodash/underscore, thought about restructuring the backend... Not really sure where to go from here.
Complete project code at github
Since there is not much details available as to how your backend works or is handling the data I am assuming the problem is with generating the JSON.
What I would do is change the way Angular posts the data to the server, for example:
the Save function:
$scope.save = function() {
var url = 'http:127.0.0.1:3000/url/you/send/your/data/to',
json = JSON.stringify($scope.quote);
$http({
method: 'POST',
url: url,
data: json,
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
$location.path('#/scrap');
});
};
This will give you more control, and will make sure you control how the data gets turned into proper JSON, in this case using the .stringify() method of the JSON object.
I see from your comments that you are concerned with indexing; conventionally objects that sync with the server have a property id that represents their database id's NOT their client array index. This is a good way to keep the model data on the client a representation of the truth on your server side.
There are quite some libraries out there that help with this process client side, I would suggest - since you are using Angular already - reading into Angular Resource.
NOTE: if you want to support older browsers with the JSON.stringify() method, make sure you use Crockford's JSON2.js

Categories