This feels like a really stupid question, but my lack of JS knowledge combined with lack of AWS knowledge has me in a tight spot! I'm just trying to get to grips with a basic AWS stack i.e. Lambda/Dynamo/API Gateway for some basic API work.
If I want a simple API endpoint to handle PUT requests e.g. https://my.endpoint.amazonaws.com/users. If I have a DynamoDB table with a composite primary key of userID and timestamp I could use the code snippet below to take the unknown data (attributes that weren't known when setting a schema), but this obviously doesn't work well
const dynamo = new AWS.DynamoDB.DocumentClient();
let requestJSON = JSON.parse(event.body);
await dynamo
.put({
TableName: "myDynamoTable",
Item: {
userID: requestJSON.userID,
timestamp: requestJSON.timestamp,
data: requestJSON.data
}
})
.promise();
I could send a PUT request with the following JSON
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
}
but then address and name get shoved into a single DynamoDB attribute named data. How do I construct the node code to create a new attribute named address and one named name with the corresponding values, if I didn't know these attributes i.e. I want to use JSON in my request like below, but assuming I don't know this and can't use requestJSON.address
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"address": "Elm Street",
"name": "Glen"
}
You can use the spread operator, for example:
const data = {
address: "Elm Street",
name: "Glen",
};
const item = {
userID: "aaaa1111",
timestamp: 1649677057,
...data,
};
console.log("item:", item);
If you insist on the API contract as
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
}
then you can do mapping on the TypeScript level
const request: {userID: string, timestamp: number, data: any} = {
"userID": "aaaa1111",
"timestamp": 1649677057,
"data": {
"address": "Elm Street",
"name": "Glen"
}
};
const ddbObject: any = {
"userID": request.userID,
"timestamp": request.timestamp
};
Object
.keys(request.data)
.forEach(key => ddbObject[key] = request.data[key]);
Representation of ddbObject is
{
"userID": "aaaa1111",
"timestamp": 1649677057,
"address": "Elm Street",
"name": "Glen"
}
Related
So I am reasonably new to using API's with Js but I am struggling a lot to understand how the Google Fit API works. I am attempting to add a new Workout's data to the API by adding a session and some data for the intensity (heart points) of the session. I can get the session to appear correctly but run into constant errors when I try to create a dataSource and add a point to it for the session. It would be greatly appreciated if someone could help me to fix my code to achieve this or could direct me to a more thorough example of similar code as the API docs don't seem to be too well detailed with examples etc. Thanks in advance.
Here's the 3 api calls that I have written so far, one for creating the DataSource, one for the DataPoint and one for the Session. The session works correctly and adds a session of 1 hr for the correct activity but I am unable to get any of the other API requests to work.
Data Source :
``gapi.client.fitness.users.dataSources.create({
"userId":"me",
"resource": {
"application": {
"name": "LittleWorkouts"
},
"dataType": {"field":[{
"format": "floatPoint",
"name": "com.google.heart_minutes"
}],
"name": "com.google.heart_minutes"
},
"device": {
"manufacturer": "op",
"model": "6",
"type": "phone",
"uid": "1000019",
"version": "1"
},
"type": "raw"
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error 1", err); });
``
Data Point :
``
gapi.client.fitness.users.dataSources.datasets.patch({
"dataSourceId":"raw:com.google.heart_minutes:292824132082:op:6:1000019",
"userId": "me",
"datasetId": "1592087806561000000-1592287806561000000",
"resource": {
"minStartTimeNs": "1592087806561000000",
"maxEndTimeNs": "1592287806561000000",
"dataSourceId": "raw:com.google.heart_minutes:292824132082:op:6:1000019",
"point": [
{
"startTimeNanos": "1592087806561000000",
"endTimeNanos": "1592287806561000000",
"value": [
{
"fpVal": 89.1
}
],
"dataTypeName": "com.google.heart_minutes"
}
]
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error 2", err); });
``
Session :
``gapi.client.fitness.users.sessions.update({
"userId":"me",
"sessionId": "someSessionId19",
"id": "someSessionId19",
"name": "Awesome Workout19",
"description": "A very intense workout",
"startTimeMillis": new Date().getTime() - 3600000,
"endTimeMillis": new Date().getTime(),
"version": 1,
"lastModifiedToken": "exampleToken",
"application": {
"detailsUrl": "http://example.com",
"name": "LittleWorkouts",
"version": "1.0"
},
"activityType": 21,
"activeTimeMillis": 3600000
}).then((res) => {console.log(res)});
console.log('res')
//request.execute((res) => {console.log(res);console.log('executrd')})
console.log(auth2.currentUser.get().getBasicProfile().getGivenName());
var request2 = gapi.client.fitness.users.sessions.list({
"userId":"me"
}).then((res) => {console.log(res)})
``
Error message
{message: "Unable to fetch DataSource for Dataset: raw:com.google.heart_minutes:292824132082:op:6:1000019", domain: "global", reason: "invalidArgument"}
It looks like it could be that you're trying to pass in the wrong fields for the data type: if you want to use a standard data type (like com.google.heart_minutes), you should either pass the exact fields of the standard data type (the field should be called "intensity"); or just pass the data type name, and the backend will fill them in for you.
So, if you change the data type to
"dataType": {"name": "com.google.heart_minutes"}
It should work.
Then, you need to use the data source ID returned from that request for the data points.
Awesome, so after some support in the comments I have some working code to add a new session with data from a previously defined data source using 3 API calls. The first call is to create a data source and only needs to be run once. The second and third then add a data point to a data set and creates a new session for the workout respectively. Here's the final working code:
Data Source:
/*
gapi.client.fitness.users.dataSources.create({
"userId":"me",
"resource": {
"application": {
"name": "LittleWorkouts"
},
"dataType": {
"name": "com.google.heart_minutes"
},
"device": {
"manufacturer": "op",
"model": "6",
"type": "phone",
"uid": "1000020",
"version": "1"
},
"type": "raw"
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error 1", err); });
*/
Data and Data Set:
gapi.client.fitness.users.dataSources.datasets.patch({
"dataSourceId":"raw:com.google.heart_minutes:108881196053:op:6:1000020",
"userId": "me",
"datasetId": z,
"resource": {
"minStartTimeNs": workoutStartTime * 1000000,
"maxEndTimeNs": workoutEndTime * 1000000,
"dataSourceId": "raw:com.google.heart_minutes:108881196053:op:6:1000020",
"point": [
{
"originDataSourceId": "raw:com.google.heart_minutes:108881196053:op:6:1000020",
"value": [
{
"fpVal": 8
}
],
"dataTypeName": "com.google.heart_minutes",
"endTimeNanos": workoutEndTime * 1000000,
"startTimeNanos": workoutStartTime * 1000000,
}
]
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error 2", err); });
Session:
gapi.client.fitness.users.sessions.update({
"userId":"me",
"sessionId": id,
"id": id,
"name": "Morning Workout",
"description": "A very intense workout",
"startTimeMillis": workoutStartTime,
"endTimeMillis": workoutEndTime,
"version": 1,
"lastModifiedToken": "exampleToken",
"application": {
"detailsUrl": "http://example.com",
"name": "LittleWorkouts",
"version": "1.0"
},
"activityType": 21,
"activeTimeMillis": workoutEndTime - workoutStartTime
}).then((res) => {console.log(res)});
console.log('res')
I am just new to typeorm , I am using nodejs/nestjs , I am trying to create a query where in data from the database which is the course could be filter by instructor which is the firstname and lastname , filter by course_name and filter courses by subject. I tried using 'where' and 'orWhere' but cant seem to wrap things up, Anyone can give an advice of a better implementation ? Thank you. Much appreciated.
The query below is working , I am having trouble with the "where" condition
Code
async findAll(options: IPaginationOptions, query): Promise<Pagination<CourseEntity>> {
console.log('query :', query);
const courses = await getRepository(CourseEntity)
.createQueryBuilder('course')
.leftJoinAndSelect('course.user', 'user')
.leftJoinAndSelect('course.subject', 'subject')
// eslint-disable-next-line #typescript-eslint/camelcase
.where('course.course_name = :course_name', { course_name: query.course_name });
return paginate<CourseEntity>(courses, options);
}
here is the query param
query : { limit: '10', firstname: 'mark', lastname: 'gunn' , course_name: 'Comscie'}
Sample data from the database
{
"id": 4,
"course_name": "BS-IT",
"description": "BS-IT DBMS",
"created": "2020-03-19T16:40:46.000Z",
"updated": "2020-03-19T16:40:46.000Z",
"user": {
"id": 20,
"firstname": "Mark",
"lastname": "Gunn",
"role": "Instructor",
"email": "mark#gmail.com",
"isActive": false,
"created": "2020-03-19T16:06:21.000Z",
"updated": "2020-03-19T16:06:34.000Z"
},
"subject": {
"id": 2,
"subject_name": "IT 100",
"description": "Fundamandetals",
"created": "2020-03-18T03:58:34.000Z",
"updated": "2020-03-18T03:58:34.000Z"
}
}
It looks good. Just add other conditions with andWhere
For my project with Typeorm, I prefer use the Find Option Object (https://typeorm.io/#/find-options), because it's easier to generate request from an object but you can't do some advanced join (but in your case it's totally ok)
They are not better implementation just multiple solutions.
I'm a beginner and would like to know how I can get a specific object from an array
I have an Array that looks like this:
data {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
},
To get the data from above I would do something like this:
return this.data.orderid
But how can I go deeper and get the status in userinfo?
return this.data.orderid.userinfo.status
doesn't work... anyone have any ideas?
A few points:
data is not an array, is an Object (see the curly braces, arrays have squared brackets). To be really precise, your syntax is invalid, but I assume you wanted to type data = { ... }, as opposed to data { ... }
Your syntax is almost correct, the only mistake you are making is that userinfo is an array, and arrays have numeric indexes (I.e. array[0], array[1]). What you are looking for is this.data.orderid.userinfo[0].status
Use data.userinfo[0].status to get the value (in your case this.data.userinfo[0].status)
var data = {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
};
console.log(data.userinfo[0].status);
User Info is an array, so you would need to access it using indexer like so:
return this.data.userinfo[0].status
MDN on arrays: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
You need to iterate over data.userinfo (it's an array)
var data = {
"orderid": 5,
"orderdate": "testurl.com",
"username": "chris",
"email": "",
"userinfo": [
{
"status": "processing",
"duedate": "" ,
}
]
};
data.userinfo.forEach(function(element) {
console.log(element.status);
});
I have an object like:
export const contact = {
_id: "1",
first:"John",
name: {
first:"John",
last:"Doe"
},
phone:"555",
email:"john#gmail.com"
};
I am reading it like
return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact._id}</h1>
</div>
)
in this scenario I am getting expected output.
return (
<div>
<h1>List of Contact</h1>
<h1>{this.props.contact.name.first}</h1>
</div>
)
But when I read the nested property I am getting error like
Uncaught TypeError: Cannot read property 'first' of undefined
How to read these king of nested objects in react? Here is my source
Three things you need to address here:
this is your contacts-data and i don't see any first property within the name object:
export const contacts = {
"name": "mkyong",
"age": 30,
"address": {
"streetAddress": "88 8nd Street",
"city": "New York"
},
"phoneNumber": [{
"type": "home",
"number": "111 111-1111"
}, {
"type": "fax",
"number": "222 222-2222"
}]
};
You are calling this.props.fetchContacts(); on componentDidMount, hence in the first render call the state is still empty, the action call and the reducer will pass new props or change the state then you get to the second render call and that's the moment you have the data ready for use.
So you should check for the existing of the data before you try to use it. one way is to just conditionally render it (of course there are better ways to do it, this is just to make a point):
render() {
const { contacts } = this.props;
return (
<div>
<h1>List of Contacts</h1>
<h2>{contacts && contacts.name && contacts.name.first
//still getting error. "this.props.contacts.name" alone works
}</h2>
<h2>{contacts && contacts.address && contacts.address.city}</h2>
</div>
)
}
You are trying to use this.props.contact.name.first is that a typo? shouldnt it be contacts instead of contact?
EDIT:
As a followup for your comment, as a general rule in JavaScript (or any other language for that manner) you should always check the existence reference of an object before you are trying to access it's properties.
As for your use case you can use defaultProps if you must have a value to render or you can even simplify the scheme of your data.
This is much simpler to manage:
export const contacts =
{
"fName": "mkyong",
"lName": "lasty",
"age": 30,
"streetAddress": "88 8nd Street",
"city": "New York",
"homeNumber": "111 111-1111",
"faxNumber": "222 222-2222"
};
Than this:
export const contacts =
{"name": "mkyong",
"age": 30,
"address": {
"streetAddress": "88 8nd Street",
"city": "New York"
},
"phoneNumber": [
{
"type": "home",
"number": "111 111-1111"
},
{
"type": "fax",
"number": "222 222-2222"
}
]
};
I'm having some problems when trying to retrieve values from a JSON response sent via the $.post() method in jQuery. Here is the script:
var clickedName = $('#customerId').val();
$.post("/customer-search", { name: clickedName }).done( function(response) {
var results = $.parseJSON(response);
console.log(results);
$('#account-name').html(results.firstname + ' ' + results.lastname);
$('#email').html(results.email);
$('#telephone').html(results.telephone);
if (results.fax) {
$('#fax').html(results.fax);
} else {
$('#fax').html('n/a');
}
$('#personal').fadeIn();
return false;
});
Just to explain, I'm using twitter typeahead in a Symfony2 project, and basically this script will fire when a name is clicked (selected) from the list after typing. The customer-search URL runs a search of the database as follows:
$q = $request->request->get('name');
$em = $this->getDoctrine()->getManager();
$customer = $em->getRepository('AppBundle:Oc73Customer')->findLikeName($q);
$addresses = $em->getRepository('AppBundle:Oc73Address')->findByCustomerId($customer[0]['customerId']);
$results = array();
$results['customer'] = $customer;
$results['addresses'] = $addresses;
return new Response(json_encode($results));
Which will successfully return a Json encoded response, and the value of 'response' which is printed in the console (as per the jquery above) is:
{
"customer": [{
"firstname": "Mike",
"lastname": "Emerson",
"email": "xxxx#xxxx.co.uk",
"telephone": "01234 5678910",
"fax": null,
"password": "8e1f951c310af4c20e2cd6b68dee506ac685d7ae",
"salt": "e2b9e6ced",
"cart": null,
"wishlist": null,
"newsletter": 0,
"addressId": 84,
"customerGroupId": 1,
"ip": null,
"status": 1,
"approved": 1,
"token": null,
"dateAdded": {
"date": "2016-02-16 12:59:28.000000",
"timezone_type": 3,
"timezone": "Europe/Berlin"
},
"availCredit": null,
"customerId": 75
}],
"addresses": [{}]
}
I am trying to retrieve the customer details by using the method I always use, so to get the firstname, I use results.firstname where results is a parsed JSON string, as written in my jQuery response.
However, all I get from results.firstname is undefined, even when it clearly is defined. So, basically, I'm wondering what I am doing wrong?
Hope someone can shed some light on my problem.
The properties you're trying to access are objects in the customer array, not on the parent object itself. Assuming that the response only ever contains one customer object then you can use result.customer[0], like this:
$.post("/customer-search", { name: clickedName }).done(function(response) {
var results = $.parseJSON(response);
var customer = response.customer[0];
$('#account-name').html(customer.firstname + ' ' + customer.lastname);
$('#email').html(customer.email);
$('#telephone').html(customer.telephone);
$('#fax').html(customer.fax ? customer.fax : 'n/a');
$('#personal').fadeIn();
});
If it's possible that multiple customer objects will be returned in the array the you would need to amend your code to loop through those objects and build the HTML to display them all - without using id attributes.
I was able to access it like "results.customer[0].firstname"
var cus =
{
"customer": [{
"firstname": "Mike",
"lastname": "Emerson",
"email": "xxxx#xxxx.co.uk",
"telephone": "01234 5678910",
"fax": null,
"password": "8e1f951c310af4c20e2cd6b68dee506ac685d7ae",
"salt": "e2b9e6ced",
"cart": null,
"wishlist": null,
"newsletter": 0,
"addressId": 84,
"customerGroupId": 1,
"ip": null,
"status": 1,
"approved": 1,
"token": null,
"dateAdded": {
"date": "2016-02-16 12:59:28.000000",
"timezone_type": 3,
"timezone": "Europe/Berlin"
},
"availCredit": null,
"customerId": 75
}],
"addresses": [{}]
}
alert(cus.customer[0].firstname);