Changing date value in object in Node - javascript

For example i have a get request which takes some data from mongo db:
const getAllContracts = async (req, res) => {
const contracts = await Contract.find({});
res.status(StatusCodes.OK).json({ contracts, count: contracts.length });
};
As response it sends:
{
"contracts": [
{
"_id": "637cbd3279de1dd12dd7d2f9",
"tenant": "Nazar",
"manager": "Misha",
"object": "Автовокзал",
"price": 99,
"area": 335,
"status": "Активний",
"activeFrom": "2022-11-16T00:00:00.000Z",
"activeUntil": "2022-11-18T00:00:00.000Z",
"createdBy": "6372c4bc0c02f9ccf3363fe0",
"contractManualId": "321a",
"contractReason": "IDK",
"contractComment": "Vasya",
"createdAt": "2022-11-22T12:14:42.248Z",
"updatedAt": "2022-11-22T12:14:42.248Z",
"__v": 0
},
{
"_id": "637cbd4d79de1dd12dd7d2fc",
"tenant": "Nazar1111",
"manager": "Misha",
"object": "Автовокзал",
"price": 99,
"area": 335,
"status": "Активний",
"activeFrom": "2022-11-16T00:00:00.000Z",
"activeUntil": "2022-11-18T00:00:00.000Z",
"createdBy": "6372c4bc0c02f9ccf3363fe0",
"contractManualId": "321a",
"contractReason": "IDK",
"contractComment": "Vasya",
"createdAt": "2022-11-22T12:15:09.755Z",
"updatedAt": "2022-11-22T12:15:09.755Z",
"__v": 0
}
],
"count": 2
}
I would like to change response date formats in activeFrom and activeUntil to dd-mm-yyyy but idk how to do that. For example 2022-11-16T00:00:00.000Z i want to change to 16.11.2022

Simple answer:
Loop over contracts and modify the properties
contracts.map((contract) => {
const activeFromDate = new Date(contract.activeFrom);
contract.activeFrom = formatDate(activeFromDate);
const activeUntilDate = new Date(contract.activeUntil);
contract.activeUntil = formatDate(activeUntilDate);
return contract;
});
function formatDate(date) {
// the +1 is because getMonth is zero-based.
return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`
}
But couple of thoughts:
1.) If you're passing this to UI code it would be "cleaner" for the UI to do this formatting.
2.) IF you have to do this on the backend return both the formatted and raw data rather than the inplace update like above.
So same structure but instead of assigning to contract.activeFrom you should assign the resultant to contract.formattedActiveFrom and return both properties to the UI. That way if they need to do any additional tinkering with the date they have it available in a format that's easy to use.

Related

How can I get all results in ReactiveList

I've tried to use on all data but it doesn't work since I can get only the number of results as stated in the 'size' parameter. Here part of my code.
<ReactiveList
componentId="results"
dataField="original_title"
size={1}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
onAllData={this.onAllData}
/>
onAllData(shops) {
let result = null;
if (shops !== null) {
console.log(shops.length);
result = shops.map((marker) => (
<ListItem>
<Thumbnail square size={80} source={{ uri: 'https://dummyimage.com/80x80/000/fff' }} />
<Body>
<Text>{marker.name}</Text>
<Text note>{marker.dis}</Text>
</Body>
</ListItem>
))
return result;
}
}
There are a couple of ways you can go about this problem:
Rendering all results with infinite loading
onAllData will give the number of results specified in the size prop. Usually, its not a good idea to set a very high size since it will take more time fetching and rendering the results. A good alternative for this is to use infinite scrolling by setting the pagination prop to false and setting a value in size prop which tells the component how many results to fetch when you reach the end of the list.
Fetching all results using scroll API
tl;dr Demo
Note
This answer uses reactivesearch for web (for demonstration) but you can use the same props in reactivesearch-native since the API is same.
The above approach works fine if you're only interested in rendering the results. But if you wish to fetch all the results for the current query, you can use the scroll API from Elasticsearch. You can use ReactiveList to get the current query and then use it together with the scroll API.
For this purpose, you can make use of the onQueryChange prop on ReactiveList:
First specify an onQueryChange prop on the ReactiveList which receives the previous and current query as parameters:
onQueryChange={(prev, next) => ...}
This function will be invoked each time the query is changed so you can write a logic to fetch the hits for the current query (received in the next parameter) whenever required.
A scroll API call returns the results in the following format:
{
"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoAgAAAAClGlY4FlotbmJJZXA0U09lMlZFMUNyQ3M2M0EAAAAApRpWORZaLW5iSWVwNFNPZTJWRTFDckNzNjNB",
"took": 0,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 9407,
"max_score": 1,
"hits": [
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5676",
"_score": 1,
"_source": {
"authors": "Arthur C. Clarke, Gentry Lee",
"average_rating": 3.76,
"average_rating_rounded": 4,
"books_count": 48,
"id": 5676,
"image": "https://images.gr-assets.com/books/1375814957l/112518.jpg",
"image_medium": "https://images.gr-assets.com/books/1375814957m/112518.jpg",
"isbn": "1857230213",
"language_code": "eng",
"original_publication_year": 1991,
"original_series": "Rama",
"original_title": "The Garden of Rama (Rama, #3)",
"ratings_count": 16389,
"title": "The Garden of Rama (Rama, #3)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5681",
"_score": 1,
"_source": {
"authors": "Darren Shan",
"average_rating": 4.22,
"average_rating_rounded": 4,
"books_count": 52,
"id": 5681,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "",
"language_code": "",
"original_publication_year": 2003,
"original_series": "Cirque Du Freak",
"original_title": "Killers of the Dawn (Cirque Du Freak, #9)",
"ratings_count": 18194,
"title": "Killers of the Dawn (Cirque Du Freak, #9)"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5683",
"_score": 1,
"_source": {
"authors": "Laura Joffe Numeroff, Felicia Bond",
"average_rating": 4.16,
"average_rating_rounded": 4,
"books_count": 13,
"id": 5683,
"image": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"image_medium": "https://s.gr-assets.com/assets/nophoto/book/111x148-bcc042a9c91a29c1d680899eff700a03.png",
"isbn": "60278684",
"language_code": "",
"original_publication_year": 2000,
"original_series": "",
"original_title": "If You Take a Mouse to the Movies",
"ratings_count": 17938,
"title": "If You Take a Mouse to the Movies"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5685",
"_score": 1,
"_source": {
"authors": "Orson Scott Card, James Cameron",
"average_rating": 4.06,
"average_rating_rounded": 4,
"books_count": 15,
"id": 5685,
"image": "https://images.gr-assets.com/books/1225165505l/40289.jpg",
"image_medium": "https://images.gr-assets.com/books/1225165505m/40289.jpg",
"isbn": "99690608",
"language_code": "eng",
"original_publication_year": 1989,
"original_series": "",
"original_title": "The Abyss",
"ratings_count": 16318,
"title": "The Abyss"
}
},
{
"_index": "good-books-ds",
"_type": "good-books-ds",
"_id": "5687",
"_score": 1,
"_source": {
"authors": "Katarina Bivald, Alice Menzies",
"average_rating": 3.56,
"average_rating_rounded": 4,
"books_count": 63,
"id": 5687,
"image": "https://images.gr-assets.com/books/1452107441l/25573977.jpg",
"image_medium": "https://images.gr-assets.com/books/1452107441m/25573977.jpg",
"isbn": "149262344X",
"language_code": "eng",
"original_publication_year": 2013,
"original_series": "",
"original_title": "Läsarna i Broken Wheel rekommenderar",
"ratings_count": 14571,
"title": "The Readers of Broken Wheel Recommend"
}
}
]
}
}
The value received as _scroll_id can be passed to the scroll API to fetch the next set of results and so on till the number of hits is zero.
Note
If your cluster has a lot of data, its not a good idea to run this logic to fetch all the results every time the query changes. You can add a condition to limit the number of results fetched or store the current query in state and only fetch all the results when required.
Here's an example on how you can implement this with ReactiveList. In the example I'm fetching the results each time the query changes but you can modify it to fetch results conditionally instead:
In your render function:
<ReactiveList
...
size={10}
onQueryChange={this.handleQueryChange}
/>
Here's how the handleQueryChange function can look like. This will give you all the results for the current query:
handleQueryChange = async (prev, next) => {
// avoid fetching the results for match_all query since dataset is large
if (next && !next.query.match_all) {
console.log('Fetching all results for query:', next);
// modify the query size here if needed (currently it is 10)
// initial url to obtain scroll id is different
const initialResults = await this.fetchResults(next, url);
// keep scrolling till hits are present
// NOTE: careful if you've a lot of results,
// in that case you might want to add a condition to limit calls to scroll API
const scrollResults = await this.fetchScrollResults({
scroll: "1m",
scroll_id: initialResults._scroll_id
});
// combine the two to get all results
// concat hits from initialResults with hits from scrollResults
const allResults = initialResults.hits.hits.concat(scrollResults);
console.log(`${allResults.length} results found:`, allResults);
}
};
Its using two functions for fetching the results initially and later with the scroll_id. The endpoints for both are different, which you can find in the demo. Here's how the first fetchResults looks like:
fetchResults = (query, api) => {
return fetch(api, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Basic ${btoa(credentials)}`
},
body: JSON.stringify(query)
})
.then(res => res.json())
.catch(err => console.error(err));
};
The fetchScrollResults will use the scroll API to fetch results till the hits obtained are 0.
fetchScrollResults = async query => {
const res = await this.fetchResults(query, scrollUrl);
const { hits } = res.hits;
if (hits.length) {
return [
...hits,
...(await this.fetchScrollResults({
scroll: "1m",
scroll_id: res._scroll_id
}))
];
}
return [];
};
Check the demo, results will appear in the console.
You are missing a key that identify unique components and you also need to wrap element inside function. If function is called properly and your array have elements this should work.
onAllData(shops) {
let result = null;
if (shops !== null) {
console.log(shops.length);
result = shops.map((marker,index) => { return (
<ListItem key={index}>
<Thumbnail square size={80} source={{ uri: 'https://dummyimage.com/80x80/000/fff' }} />
<Body>
<Text>{marker.name}</Text>
<Text note>{marker.dis}</Text>
</Body>
</ListItem>
)})
return result;
}

Differences with API's when trying to pull data

I am having difficulty with a pulling some data from an API for a school project using Jquery.
If I use the following coinmaketcap API I get the following response
https://api.coinmarketcap.com/v1/ticker/bitcoin/
[
{
"id": "bitcoin",
"name": "Bitcoin",
"symbol": "BTC",
"rank": "1",
"price_usd": "8854.92",
"price_btc": "1.0",
"24h_volume_usd": "6759730000.0",
"market_cap_usd": "150480289107",
"available_supply": "16993975.0",
"total_supply": "16993975.0",
"max_supply": "21000000.0",
"percent_change_1h": "-0.13",
"percent_change_24h": "0.12",
"percent_change_7d": "8.3",
"last_updated": "1524459272"
}
]
I get am able to get the symbol for Bitcoin and place it into a variable by using this code
> $.getJSON('https://api.coinmarketcap.com/v1/ticker/btc/',
> function(data){
> var symbol = (data[0].symbol)
> })
Once I have it I can place it in a div.
However when I use cryptocompare API I don't get anything back
https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC,&tsym=USD
$.getJSON('https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD', function(data){
var symbol = (data[0].Internal)
});
This is the response -
{
"Message": "Success",
"Type": 100,
"Data": [
{
"CoinInfo": {
"Id": "1182",
"Name": "BTC",
"FullName": "Bitcoin",
"Internal": "BTC",
"ImageUrl": "/media/19633/btc.png",
"Url": "/coins/btc/overview",
"Algorithm": "SHA256",
"ProofType": "PoW",
"NetHashesPerSecond": 27483320229.3688,
"BlockNumber": 518932,
"BlockTime": 600,
"BlockReward": 12.5,
"Type": 1,
"DocumentType": "Webpagecoinp"
},
"ConversionInfo": {
"Conversion": "direct",
"ConversionSymbol": "",
"CurrencyFrom": "BTC",
"CurrencyTo": "USD",
"Market": "CCCAGG",
"Supply": 16986575,
"TotalVolume24H": 380849.0498955779,
"SubBase": "5~",
"SubsNeeded": [
"5~CCCAGG~BTC~USD"
],
"RAW": [
"5~CCCAGG~BTC~USD~4~8875.23~1524460635~0.00477012~42.152119404000004~231254719~10820.885574747872~96327075.76938197~66326.58563159907~593473019.8524572~8823.46~8917.05~8804.2~8864.31~9065~8780.91~Bitfinex~7ffe9"
]
}
}
]
}
Why is the second piece of code not working? Please help!
The second API is returning an object (in JSON format), not an array - see how the first character is { and how it has keys and values? You need to access the appropriate property to get the value you want. [0] notation indicates you're trying to access the first element of the array, but the outer object is not an array in this situation.
$.getJSON('https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD',
function(data){
var symbol = data.Data[0].CoinInfo.Internal;
});
In both the cases, we are getting data in different form. So, To get the 'BTC' in variable .
for 1st case -> symbol = data[0] ['symbol']
for 2nd case -> symbol = data['Data'][0]['CoinInfo']['Internal']
one is an [array of JSON] while other is an [object having key 'Data' with array value].

Assign array of JSON objects to array of interface Angular/Typescript

Currently, this works and doesn't give my error while running but my text editor is giving me an error that says property 'categories' does not exist on type 'CategoryInterface[]' (on the line where response.categories is assigned to variable) so I'm not sure if I'm doing things right.
public categories: CategoryInterface[];
.subscribe((response: CategoryInterface[]) => {
this.categories = response.categories;
console.log(this.categories);
});
My backend returns this:
{
"categories": [
{
"categoryId": 1,
"name": "Important",
"description": "This category is important.",
"order": 1,
"createdBy": null,
"createdAt": "2017-11-25 12:09:04",
"updatedBy": null,
"updatedAt": "2018-01-17 23:53:25",
"categoryBoards": [
{
"categoryBoardId": 1,
"categoryId": 1,
"name": "Announcements",
"description": null,
"order": 2,
"createdBy": null,
"createdAt": "2017-11-25 12:09:49",
"updatedBy": null,
"updatedAt": "2018-01-18 00:09:02"
},
{
"categoryBoardId": 23,
"categoryId": 1,
"name": "Rules",
"description": null,
"order": 1,
"createdBy": null,
"createdAt": "2018-01-18 00:08:57",
"updatedBy": null,
"updatedAt": "2018-01-19 00:05:51"
}
]
}
]
}
You are trying to cast your api response to an array of CategoryInterface which is not the case, you better use your subscribe method like this:
.subscribe((response: any) => {
this.categories = <CategoryInterface[]> response.categories;
console.log(this.categories);
});
It's the your api response categories which needs to be casted to CategoryInterface[]
Bonus: The angular style-guide notice that you need to declare classes instead of interfaces and you don't have to suffix the class name with Interface, so just name your CategoryInterface to Category.
You get the error because you declare response as a CategoryInterface[], but response.categories is actually the CategoryInterface[]. response is just a wrapper around the array. All the types are stripped out when the typescript is converted to javascript, which is why it works fine at runtime.

Removing unwanted JSON data using JAVASCRIPT

I'm new to JSON and Javascript and had to make a table in Cloudant NoSQL.
So, I collected Weather data from a Weather Company in JSON format and sent it to Cloudant, but there was some data in JSON which wasn't relevant to the table I wanted to create.
Is there a way to remove the metadata and the column name "observation" from the JSON data I received using javascript?
JSON data I have:
{
"metadata": {
"language": "en-US",
"transaction_id": "1503766402801:1454518918",
"version": "1",
"latitude": 12.83,
"longitude": 77.68,
"expire_time_gmt": 1503771300,
"status_code": 200
},
"observation": {
"key": "43295",
"class": "observation",
"expire_time_gmt": 1503771300,
"obs_id": "43295",
"obs_name": "Bangalore",
"valid_time_gmt": 1503759600,
"day_ind": "N",
"temp": 75,
"wx_icon": 29
}
}
JSON data I want
{
"_id": "2e5e0da1f82157dd6f5d381a4c9ff84e",
"_rev": "1-b7a92ae5f96b051f0add3b26a14543c2",
"key": "43295",
"class": "observation",
"expire_time_gmt": 1503771300,
"obs_id": "43295",
"obs_name": "Bangalore",
"valid_time_gmt": 1503759600,
"day_ind": "N",
"temp": 75,
"wx_icon": 29
}
Thank you.
EDIT
I'm able to remove metadata using "delete data.metadata;", where data contains the JSON, but I still can't remove the "observation" word and the curly braces in the end.
Assuming your JSON is parsed, you can just assign all keys from all nested objects to a new object.
var myData = {
"metadata": {
"language": "en-US",
"transaction_id": "1503766402801:1454518918",
"version": "1",
"latitude": 12.83,
"longitude": 77.68,
"expire_time_gmt": 1503771300,
"status_code": 200
},
"observation": {
"key": "43295",
"class": "observation",
"expire_time_gmt": 1503771300,
"obs_id": "43295",
"obs_name": "Bangalore",
"valid_time_gmt": 1503759600,
"day_ind": "N",
"temp": 75,
"wx_icon": 29
}
}
myData = Object.keys(myData)
.reduce((res, key) => Object.assign(res, myData[key]), {});
console.log(myData);
There are some extra keys in your result. Not sure where those are coming from.
If there are some extra properties to delete, you can use delete to get rid of those.
["latitude", "longitude"].forEach(k => delete myData[k]);
Or perhaps I misunderstood. I though you wanted a consolidation. If you only wanted the observation object, then just assign it to the original variable.
myData = myData.observation;
And add whatever other properties you'd like.
You can create a new json object before sending. Using lodash should be an easy solution in extending
// Assume result has your json data
var wantedJson = _.extend({}, result.observation, result.metadata);
If you are not bothered about the order of the elements, this is the simplest way:
var result = {
"metadata": {
"language": "en-US",
"transaction_id": "1503766402801:1454518918",
"version": "1",
"latitude": 12.83,
"longitude": 77.68,
"expire_time_gmt": 1503771300,
"status_code": 200
},
"observation": {
"key": "43295",
"class": "observation",
"expire_time_gmt": 1503771300,
"obs_id": "43295",
"obs_name": "Bangalore",
"valid_time_gmt": 1503759600,
"day_ind": "N",
"temp": 75,
"wx_icon": 29
}
}
var myjson = result.observation;
myjson._id = "2e5e0da1f82157dd6f5d381a4c9ff84e",
myjson._rev = "1-b7a92ae5f96b051f0add3b26a14543c2";
console.log(myjson);

Adding data to JSON array

I have a JSON Array inside my Node.js code with the following schema:
{
"status": "ok",
"data": [
{
"id": 1,
"active": true,
"createdAt": "2017-07-21T15:39:31.000Z",
"updatedAt": "2017-07-21T15:47:13.000Z"
}
]
}
and I want to add data so it will look like:
{
"status": "ok",
"data": [
{
"id": 1,
"active": true,
"createdAt": "2017-07-21T15:39:31.000Z",
"updatedAt": "2017-07-21T15:47:13.000Z",
"information": "someInformation"
}
]
}
Can you help me how to do this?
Thanks!
Like this? access the data property, of the obj variable, and the first element in that array, then set a new property on that object equal to your string.
var obj = {
"status": "ok",
"data": [
{
"id": 1,
"active": true,
"createdAt": "2017-07-21T15:39:31.000Z",
"updatedAt": "2017-07-21T15:47:13.000Z"
}
]
};
obj.data[0].information = "someInformation";
console.log( obj );
Since you have already the JSON you should firstly parse it, because JSON is a string. After parsing you will get object that should be saved in some variable, then you can access it as general object and add the property you want. Then you have to transform it to JSON string again. It will be like this
var parsed = JSON.parse(data); // Now we are transforming JSON string into the object
//Now you may do whatever you want
parsed.newprop = 'some text';
parsed.hello = 'Hellow world';
data = JSON.stringify(parsed); // Now we are replacing the previous version of JSON string to new version with additional properties
var dataContainer = {
"status": "ok",
"data": [
{
"id": 1,
"active": true,
"createdAt": "2017-07-21T15:39:31.000Z",
"updatedAt": "2017-07-21T15:47:13.000Z"
}
]
};
for(var i = 0; i < dataContainer.data.length; i++) {
dataContainer['data'][i]['information'] = "some information";
}
Hope it helps you !

Categories