NodeJS - Iterating over API response to access inner fields from object? - javascript

I have the following NodeJs code in my AWS lambda as part of a larger lambda.
It calls an external API to return data regarding tournament schedules, I am able to get the response back from the API but I am unsure how to access the fields in the JSON response that I need.
This is my first time working with JS and NodeJS so I am unfamiliar with this.
const promise = new Promise((resolve, reject) => {
const options = {
host: 'MY_HOST',
path: 'MY_PATH',
headers: {
'key': 'value'
}
}
const req = https.get(options, res => {
let rawData = '';
res.on('data', chunk => {
rawData += chunk;
});
res.on('end', () => {
try {
resolve(JSON.parse(rawData));
} catch (err) {
reject(new Error(err));
}
});
});
req.on('error', err => {
reject(new Error(err));
});
});
// TODO - get promise result and iterate response
promise.then();
The response return is as follows (only showing first object for simplicity):
{
"_id": {
"$oid": "6346b02601a3c2111621c8e4"
},
"orgId": "1",
"year": "2023",
"schedule": [
{
"tournId": "464",
"name": "Fortinet Championship",
"timeZone": "America/Los_Angeles",
"date": {
"weekNumber": "37",
"start": {
"$date": {
"$numberLong": "1663200000000"
}
},
"end": {
"$date": {
"$numberLong": "1663459200000"
}
}
},
"format": "stroke",
"courses": [
{
"host": "Yes",
"location": {
"state": "CA",
"city": "Napa",
"country": "USA"
},
"courseName": "Silverado Resort and Spa (North Course)",
"courseId": "552"
}
],
"purse": {
"$numberInt": "8000000"
},
"winnersShare": {
"$numberInt": "1440000"
},
"fedexCupPoints": {
"$numberInt": "500"
}
}
]
}
The fields that I need access to are:
schedule[0].date.start
schedule[0].date.end
This is because I want to do e.g:
// loop each result and assert if current epoch is in the date Range
var currentTournamentId;
for(){
if(currentEpoch >= schedule.date.start && currentEpoch <= schedule.date.end) {
currentTournamentId = currentTournament.getId();
break;
}
}
How can I access these fields from the response?

Install body-parser andrequire it
let schedule = req.body.schedule;
schedule.forEach((item) => {
let start = item.date.start;
let end = item.date.end;
// do something
}

Related

Replace a value in a json file with value from another file using fs

I want to read the values of key, access, path, bucket and bucketPath and use them in the JSON file test.json.
I have a function that reads the content of configuration.js and attempts to write to test.json. Currently, I am able to write the values of bucket.I get the changed/new values and lines of null for the rest of the json.
I want to always return the new values and the other objects in the file. Also, in cases where bucket already has a value, I want it replaced by whatever is read from configuration.json
How can I fix this, and how can i change the values for the rest access, key, path and bucketpath?
index.js
const fs = require("fs").promises;
async function readJSON(filePath, values) {
const data = await fs.readFile(filePath);
try {
return JSON.parse(data);
} catch (err) {
console.log(err);
}
}
(async() => {
const credentials = await readJSON("./configuration.json");
const path = credentials.path;
const bucket = credentials.bucket;
const access = credentials.access;
const key = credentials.key;
const bucketPath = credentials.bucketPath;
const data = await jsonReader("./test.json");
const finalJSON = data.data ? .map((x) => {
if (x.type == "s3 credentials") return { ...x, bucket };
});
await fs.writeFile(
"./test.json",
JSON.stringify({
data: finalJSON
})
);
})();
test.json
{
"label": "storage record",
"data": [{
"id": "8902uw",
"type": "config",
"values": {
"access": "$access",
"key": "$key"
}
},
{
"id": "893wh002jei",
"type": "s3 credentials",
"bucket": ""
},
{
"id": "90yueps",
"type": "upload",
"input": "localhost: `$path`"
},
{
"id": "9028901",
"type": "change",
"name": "Adjust data",
"measure": [{
"t": "setter"
},
{
"p": "filename",
"to": "$join([\"$bucketPath\", data])"
}
],
"fixed": ""
}
]
}
configuration.json
{
"key": "880082",
"access": "793082",
"path": "/store",
"bucket": "testBucket",
"bucketPath": "/record"
}
Currently, when I run this, I get:
{
null,
"data": [{
null,
null,
null,
null
{
"id": "893wh002jei",
"type": "s3 credentials",
"bucket": ""
},
{
null,
null,
null
]
}
might this be a solution !
const fs = require('fs');
const fileName = './file.json';
const file = require(fileName);
file.key = "new value";
fs.writeFile(fileName, JSON.stringify(file), function writeJSON(err) {
if (err) return console.log(err);
console.log(JSON.stringify(file));
console.log('writing to ' + fileName);
});
[Updated answer]
From what you comment:
it's the same question. So when I run what I have, I get null for the other objects. I want test.json to remain the same just with updated values.
const testObj = await jsonReader("./test.json");
const finalJSON = {
...testObj,
data: testObj.data?.map((x) => {
if (x.type === 's3 credentials') {
return { ...x, bucket };
} else {
return x;
}
})
}
// which the code I gave above,
// the `finalJSON` now is the clone of the original from `test.json`
// plus updated values
await fs.writeFile(
"./test.json",
JSON.stringify(finalJSON)
);
[Original answer]
There is a problem with the function you pass to the map function.
The condition if without else.
I think you need else { return x; } to return original data if x.type is not what you expected.

Google People Api: Country not returned in Adresses field

I am trying to get the authenticated user's country by specifying "addresses" field in the People Api request as specified here.
This is the code:
router.post("/test_scope", (req, res) => {
const { idToken, accessToken } = req.body;
authenticationServices
.validateGoogleAccessToken(idToken, accessToken)
.then((response) => {
res.json(response);
});
});
const validateGoogleAccessToken = async (idToken, accessToken) => {
try {
const CLIENT_ID =
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com";
const client = new OAuth2Client(CLIENT_ID);
const ticket = await client.verifyIdToken({
idToken,
audience: CLIENT_ID,
});
const payload = ticket.getPayload();
const { OAuth2 } = google.auth;
const oauth2Client = new OAuth2();
oauth2Client.setCredentials({ access_token: accessToken });
const peopleAPI = google.people({
version: "v1",
auth: oauth2Client,
});
const { data } = await peopleAPI.people.get({
resourceName: "people/me",
personFields: "birthdays,genders,addresses",
});
const { birthdays, genders, addresses, ageRanges } = data;
return data;
} catch (error) {
console.log("error: ", error);
throw new Error("Google token validation failed");
}
};
I have set up the addresses information in the account I am using to sign-in like this:
The is the whole response I get after sending the request:
{
"resourceName": "people/XXXXXXXXXXXXXXXXx",
"etag": "%XXXXXXXXXXXXXXXXXXXXXXXXXX",
"genders": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "XXXXXXXXXXXXXXXXXXXX"
}
},
"value": "female",
"formattedValue": "Female"
}
],
"birthdays": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "1XXXXXXXXXXXXXXXXXXXXXXXX"
}
},
"date": {
"month": 8,
"day": 9
}
},
{
"metadata": {
"source": {
"type": "ACCOUNT",
"id": "XXXXXXXXXXXXXXXXXXXXXXx"
}
},
"date": {
"year": 1996,
"month": 8,
"day": 9
}
}
],
"addresses": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "111110367350060808978"
}
},
"formattedValue": "XXXXXXXXXXXXX, XXXXX, XXXXX",
"type": "home",
"formattedType": "Home"
}
],
}
As you see the country field is missing in "addresses.
NOTE: I am retrieving the idToken and the accessToken from the FrontEnd, after the user clicks on the SignIn button:
import GoogleLogin from "react-google-login";
export class LoginPage extends Component {
onGoogleSignInSucceeded(response) {
const { accessToken, tokenId } = response;
}
render() {
const { errors } = this.state;
return (
<>
<GoogleLogin
clientId="XXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com"
scope="https://www.googleapis.com/auth/user.birthday.read https://www.googleapis.com/auth/user.gender.read https://www.googleapis.com/auth/user.addresses.read"
// IMPORTANT
// https://developers.google.com/people/api/rest/v1/people/get#authorization-scopes
buttonText="Sign-in with your Google account"
onSuccess={this.onGoogleSignInSucceeded}
onFailure={this.onGoogleSignInFailed}
cookiePolicy={"single_host_origin"}
/>
</>
);
}
}
All fields on the address field are optional (see docs). This also includes the country. There is also no guarantee that the data is actually correct (the user can add invalid data to their google profile), so be careful about that and check for the verified metadata (see docs).
That being said you could try using a geocoding API to get the country from the formatted address. This could be made by using a reverse geocoding query (Google Geocoding API documentation).
Also notice that there are other fields that may contain an address. For example locations (see docs) can contain information about where they live.

Dynamic key value pair find in MongoDB

I'm facing a problem in searching for dynamic key value pairs using .find method in mongoDB.
here is my array of objects which the key value pairs can be increased...
[
{
"key" : "dynamicKey1",
"value": "dynamicValue1"
},
{
"key" : "dynamicKey2",
"value": "dynamicValu2"
},
...
]
I wish to get the result in a way that satisfies all the key value pair conditions. Something like find all documents from collection that satisfies these conditions.
So my API is this:
app.post('/search/:name', (req, res) => {
const collectionName = req.params.name;
async.eachSeries(req.body, (item, callback) => {
const database = client.db("databaseName");
const result = database.collection(collectionName).find({ [item.key]: item.value }).toArray();
result.then((doc) => {
res.json(doc)
})
callback();
});
});
the result returns two or more promises but I only need those documents that satisfies all .find queries as the result.
How should I solve it?
Thanks
Here is Insomnia POST request Image: Insomnia
Based on the Image you provided your data is of the following format in the database:
[
{
"_id": "1",
"region": "Auckland",
"anzsic_descriptor":"Agriculture",
"gas": "carbon diaoxide equivalents",
"units":"kilotonnes",
"magnitude":"carbon diaoxide equivalents",
"year": "2011",
"data_val": "764.3"
},
{
"_id": "2",
"region": "Canterbury",
"anzsic_descriptor":"Agriculture",
"gas": "carbon diaoxide equivalents",
"units":"kilotonnes",
"magnitude":"carbon diaoxide equivalents",
"year": "2011",
"data_val": "6823.16"
},
{
"_id": "3",
"region": "Bay of Plenty",
"anzsic_descriptor":"Agriculture",
"gas": "carbon diaoxide equivalents",
"units":"kilotonnes",
"magnitude":"carbon diaoxide equivalents",
"year": "2011",
"data_val": "1477.94"
}
...........
]
The /search/:name is receiving a body which is an array in the below format:
[{
"key": "year",
"value": "2011"
}, {
"key": "data_val",
"value": "764.3"
}]
You need to use a query generate as follows to generate your query first before the DB query:
const generateQuery = (arr) => {
return arr.reduce((result, item) => {
const {key, value } = item;
result[key] = value;
return result;
}, {});
};
console.log(generateQuery([{"key": "year","value": "2011"},{"key": "data_val","value": "764.3"}]))
The DB query for the generated query looks like this: mongo playground.
Then use this generated query to get the result in the endpoint, all these changes looks like below:
const generateQuery = (arr) => {
return arr.reduce((result, item) => {
const { key, value } = item;
result[key] = value;
return result;
}, {});
};
app.post('/search/:name', (req, res) => {
return new Promise((resolve, reject) => {
const collectionName = req.params.name;
const queryArry = req.body // [{"key": "year","value": "2011"},{"key": "data_val","value": "764.3"}]
const query = generateQuery(queryArry);
const database = client.db("databaseName");
database.collection(collectionName).find(query).then(result => {
return resolve(result);
}).catch(e => {
reject(e);
});
}).catch(e => {
reject(e);
})
});

Assign Variables to JSON data in node JS

I have an API End point that i am trying to assign variables to, now the one JSON data is an array and I Loop over it to get the data out in my console log, the difficulty i am having is that i want to assign variables to them.
Here is my code:
const request = require('request');
request('https://fantasy.premierleague.com/api/leagues-classic/1114549/standings/?page_new_entries=1&page_standings=1&phase=1', { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
var data = body.standings.results;
data.forEach(obj => {
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`);
});
console.log('-------------------');
});
});
and here is my JSON data:
{
"league": {
"id": 1114549,
"name": "The crew",
"created": "2020-09-11T17:36:20.083556Z",
"closed": false,
"max_entries": null,
"league_type": "x",
"scoring": "c",
"admin_entry": 3523866,
"start_event": 1,
"code_privacy": "p",
"rank": null
},
"new_entries": {
"has_next": false,
"page": 1,
"results": []
},
"standings": {
"has_next": false,
"page": 1,
"results": [
{
"id": 30771462,
"event_total": 8,
"player_name": "Mohammed Ismail",
"rank": 1,
"last_rank": 0,
"rank_sort": 1,
"total": 8,
"entry": 3808290,
"entry_name": "Moe"
}
Now I am trying to console log only the standings.result.player_name in my console log so i can use it else where, how do i do that
So my output in the console should only be "player_name": "Mohammed Ismail",
I'm not sure that i get the question, but in case if you want to get all player_name and collect it in array as example, You can do it next:
const request = require('request');
const url = 'https://fantasy.premierleague.com/api/leagues-classic/1114549/standings/?page_new_entries=1&page_standings=1&phase=1';
async function getStandings(url) {
return new Promise((resolve, reject) => {
request(
url,
{ json: true },
(err, res, body) => {
if (err) {
reject(err);
return;
}
resolve(body.standings.results);
}
);
});
}
(async () => {
const data = await getStandings(url);
// here you will receive array of stadings
console.log('data : ', data);
})();

How to fetch particular documents in elasticsearch index

I want to fetch all the data of the corresponding particular field, and have a response of the elastic search.
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 35,
"relation": "eq"
},
"max_score": 0.44183275,
"hits": [
{
"_index": "allevents",
"_type": "_doc",
"_id": "jQPDaG0BcOh3oggcguoV",
"_score": 0.44183275,
"_source": {
"category": "sessions",
"contentid": "KqRLj2lWZ3",
"clientname": "omkarpathlab",
------------------
}]
I tried search function it returning an error.
var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
host: 'aaa',
log: 'trace',
apiVersion: '7.1'
});
client.search({
"size": 20,
"query": {
"query_string": {
"default_field": "clientname",
"query": "omkarlab"
}
}
}).then((res) => {
console.log("resultData", res);
}, (err) => {
console.log("err", err);
});
enter code here
Error showing:
{ Error: [illegal_argument_exception] request [/_search] contains unrecognized parameter: [query]
Please suggest me how to solve this kind of problem.
You should specify your field under default_field, not the value you are looking for. The field you are trying to query is clientname in your case, and the value you are looking for is omkarpathlab. So your query should be as follows:
"query": {
"query_string": {
"default_field": "clientname",
"query": "omkarpathlab"
}
}
edit. But your query inside of the body property:
client.search({
"size": 20,
"body": {
"query": {
"query_string": {
"default_field": "clientname",
"query": "omkarlab"
}
}
}
}).then((res) => {
console.log("resultData", res);
}, (err) => {
console.log("err", err);
});
You can use below code to connect to elasticsearch. I have tested it on 5.6 version
'use strict'
const { Client } = require('#elastic/elasticsearch')
const client = new Client({ node: 'http://XXX:9200' })
async function run () {
// Let's search!
const { body } = await client.search({
index: 'XXX',
type : 'XXX',
body: {
query: {
match_all: {}
}
}
})
console.log(body.hits.hits)
}
run().catch(console.log)
Code is a sample from https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/search_examples.html site.
for search documentation check below link
https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#_search

Categories

Resources