How can I create a Get request in Node.js to get specific object from json? - javascript

I am optimizing an api, therefore I need to use only data that is relevant for my analysis. I have created a route that pull out of the objects, but I just need 4 of them (account_manager, fronter, closer, management_fee and sales_date)
I am currently doing this:

you can use .find() with projection to retrieve only the relevant field
try this :
const model_CancellationKPI = await CancellationKPI.find({},{
account_manager:1,
fronter:1,
closer:1,
management_fee:1,
sales_date:1
}).sort({sales_date:-1})

Related

How to append an item to a JSON stored in a file?

Im triying to write a JSON object to a DB with FS but it´s not working as expected. What i want to do is write the JSON data inside this: [] Example:
[
{"name":"jhon"},
{"name":"jhonathan"}
]
Here is the code:
Thanks.
The comment you provided doesn't make much sense, because the JSON data you provided in the post and in the comments is completely different. But I get the gist of it. I guess you have a JSON file containing an array and you want to push new items to it. Let's do this.
The thing is, when you call fs.appendFile, you're only writing to the end of the file. You're not following JSON format by doing so.
You need to do this:
Read file content.
Parse JSON text into an object.
Update the object in memory.
Write object in JSON format back to the file system.
I'll call the synchronous methods for simplicity's sake, but you should be able to convert it to async quite easily.
const path = __dirname + 'db.json'
// Reading items from the file system
const jsonData = fs.readFileSync(path)
const items = JSON.parse(jsonData)
// Add new item to the item list
items.push(newItem)
// Writing back to the file system
const newJsonString = JSON.stringify(items)
fs.writeFileSync(path, newJsonString)

SAP Cloud SDK for Javascript: Filter on Expanded Entities

I know I am reopening an old one (Perform filter on expanded entity with SAP Cloud SDK), but it was a while ago and was referencing the Java version of the API used to consume an S/4 HANA service.
I'm testing the Javascript version of the API against the SuccessFactors OData API, which is indeed able to perform filters on expanded entities, like so:
<API_HOST>/odata/v2/PerPerson?$filter=personalInfoNav/firstName eq 'MARCO'&$expand=personalInfoNav&$select=personalInfoNav/firstName, personalInfoNav/lastName&$top=20
Translated into the SDK, it would be (TypeScript):
const personList: Array<PerPerson> =
await PerPerson.requestBuilder().getAll().top(20)
.select(
PerPerson.DATE_OF_BIRTH,
PerPerson.PERSONAL_INFO_NAV.select(
PerPersonal.PERSON_ID_EXTERNAL,
PerPersonal.FIRST_NAME,
PerPersonal.LAST_NAME,
PerPersonal.GENDER
)
).filter(PerPersonal.FIRST_NAME.equals('MARCO'))
.execute({ destinationName: this.configService.get<string>('ACTIVE_DESTINATION') });
But this code does not compile because of the incompatibility of types for the filter function, which here expects a "PerPerson" type and not "PerPersonal".
I was not able to find anything about this.
Considering that the plain OData query works perfectly, anyone has been able to make this work?
Update:
I didn't initially understand that Successfactors offered this functionality on top of the protocol. There are two possible workarounds I can think of:
use new Filter, e.g.:
PerPerson.requestBuilder().getAll().top(20)
.select(
...
).filter(
new Filter('personalInfoNav/firstName', 'eq', 'MARCO')
)
...
If this doesn't work, you can call build on the request builder instead of execute, which gives you the ODataRequest object from which you can get the URL, which you'd then have to manipulate manually. Then you should be able to use the executeHttpRequest function to execute this custom request object against a destination.
Let me know if one of these work for you!
Original answer:
filtering on expanded entities on OData v2 is only possible if the relationship between the two entities is 1:1. In the case the code would look like this:
PerPerson.requestBuilder().getAll().top(20)
.select(
PerPerson.DATE_OF_BIRTH,
PerPerson.PERSONAL_INFO_NAV.select(
PerPersonal.PERSON_ID_EXTERNAL,
PerPersonal.FIRST_NAME,
PerPersonal.LAST_NAME,
PerPersonal.GENDER
)
).filter(
PerPerson.PERSONAL_INFO_NAV.filter(
PerPersonal.FIRST_NAME.equals('MARCO')
))
...
If, however, the relationship is 1:n, filtering is not possible.
Hope that helps!

Transforming JSON in a node stream with a map or template

I'm relatively new to Javascript and Node and I like to learn by doing, but my lack of awareness of Javascript design patterns makes me wary of trying to reinvent the wheel, I'd like to know from the community if what I want to do is already present in some form or another, I'm not looking for specific code for the example below, just a nudge in the right direction and what I should be searching for.
I basically want to create my own private IFTTT/Zapier for plugging data from one API to another.
I'm using the node module request to GET data from one API and then POST to another.
request supports streaming to do neat things like this:
request.get('http://example.com/api')
.pipe(request.put('http://example.com/api2'));
In between those two requests, I'd like to pipe the JSON through a transform, cherry picking the key/value pairs that I need and changing the keys to what the destination API is expecting.
request.get('http://example.com/api')
.pipe(apiToApi2Map)
.pipe(request.put('http://example.com/api2'));
Here's a JSON sample from the source API: http://pastebin.com/iKYTJCYk
And this is what I'd like to send forward: http://pastebin.com/133RhSJT
The transformed JSON in this case takes the keys from the value of each objects "attribute" key and the value from each objects "value" key.
So my questions:
Is there a framework, library or module that will make the transform step easier?
Is streaming the way I should be approaching this? It seems like an elegant way to do it, as I've created some Javascript wrapper functions with request to easily access API methods, I just need to figure out the middle step.
Would it be possible to create "templates" or "maps" for these transforms? Say I want to change the source or destination API, it would be nice to create a new file that maps the source to destination key/values required.
Hope the community can help and I'm open to any and all suggestions! :)
This is an Open Source project I'm working on, so if anyone would like to get involved, just get in touch.
Yes you're definitely on the right track. There are two stream libs I would point you towards, through which makes it easier to define your own streams, and JSONStream which helps to convert a binary stream (like what you get from request.get) into a stream of parsed JSON documents. Here's an example using both of those to get you started:
var through = require('through');
var request = require('request');
var JSONStream = require('JSONStream');
var _ = require('underscore');
// Our function(doc) here will get called to handle each
// incoming document int he attributes array of the JSON stream
var transformer = through(function(doc) {
var steps = _.findWhere(doc.items, {
label: "Steps"
});
var activeMinutes = _.findWhere(doc.items, {
label: "Active minutes"
});
var stepsGoal = _.findWhere(doc.items, {
label: "Steps goal"
});
// Push the transformed document into the outgoing stream
this.queue({
steps: steps.value,
activeMinutes: activeMinutes.value,
stepsGoal: stepsGoal.value
});
});
request
.get('http://example.com/api')
// The attributes.* here will split the JSON stream into chunks
// where each chunk is an element of the array
.pipe(JSONStream.parse('attributes.*'))
.pipe(transformer)
.pipe(request.put('http://example.com/api2'));
As Andrew pointed out there's through or event-stream, however I made something even easier to use, scramjet. It works the same way as through, but it's API is nearly identical to Arrays, so you can use map and filter methods easily.
The code for your example would be:
DataStream
.pipeline(
request.get('http://example.com/api'),
JSONStream.parse('attributes.items.*')
)
.filter((item) => item.attibute) // filter out ones without attribute
.reduce((acc, item) => {
acc[item.attribute] = item.value;
return acc;
.then((result) => request.put('http://example.com/api2', result))
;
I guess this is a little easier to use - however in this example you do accumulate the data into an object - so if the JSON's are actually much longer than this, you may want to turn it back into a JSONStream again.

Fetch Backbone Collection by Model IDs list

I have a REST API serving a few URLs:
/rest/messages
provides all messages. A message is a JSON/Backbone Model
{
title: 'foo',
body : 'bar'
}
To get a single message I have:
/rest/messages/:id
Is it possible to fetch a Backbone Collection using message IDs array? I don't want the whole message list, but just a few messages I specify by ID.
I could fetch Models one-by-one and fill up the Collection, but I'm wondering if Backbone has a cleaner way to do this.
Thanks
According to documentation, you can pass ajax options to the fetch call. So, you can pass ids as data attribute to the fetch call being done and based on it, return the respective models from the server.
For example (when doing fetch),
collection.fetch({
data : {
message_ids : [1, 3, 5] // array of the message ids you want to retrieve as models
}
})
This message_id array will be accessible as parameters (not sure of the name in your case) in the server code being executed at /rest/messages, from there you can return only specific models based on ids you receive as message_ids. The only thing you need is, client side must be aware of the ids of all the message models it needs.
You can use any data structure instead of array to send message_ids.
The url property of collection reference to the collection location on the server. When you use fetch, backbone uses that url.
The url property can be also a function that returns the url. So you can do something like that:
var ids = [1,2,3]
var messages = new MessegecCollection();
messages.url = function() {
return "/rest/messages/"+ids.join("-"); //results "/rest/messages/1-2-3"
}
messages.fetch();
You can also create a method in your collection that generated and set the url, or even fetchs a set of models.
Now all you have to do is to support this url: /rest/messages/1-2-3
Hope this helps!

How to exclude an object's id property before or during $.toJSON

I'm writing a custom REST adapter for ember-data users with a django rest framework app and need to build a JSON string to do POST/PUT. The only problem is I can't seem to chain another jQuery method after the $.toJSON that removes this.
So far I have an ember.js object that I plan to extract each property from, except my django app doesn't want the id to go along with the HTTP POST
I can get a legit string like so
$.param(record.toJSON());
This results in the following
id=0&username=dat
I'd like a quick way to exclude id when I do this toJSON (does this exist w/ out writing it by hand?) Using jQuery 1.8+
Thank you in advance
Turns out this was really simple
var json_data = record.toJSON();
delete json_data.id;
var data = $.param(json_data);
Now instead of
id=0&username=dat
I now get
username=dat

Categories

Resources