Azure mobile apps CRUD operations on SQL table (node.js backend) - node.js

This is my first post here so please don't get mad if my formatting is a bit off ;-)
I'm trying to develop a backend solution using Azure mobile apps and node.js for server side scripts. It is a steep curve as I am new to javaScript and node.js coming from the embedded world. What I have made is a custom API that can add users to a MSSQL table, which is working fine using the tables object. However, I also need to be able to delete users from the same table. My code for adding a user is:
var userTable = req.azureMobile.tables('MyfUserInfo');
item.id = uuid.v4();
userTable.insert(item).then( function (){
console.log("inserted data");
res.status(200).send(item);
});
It works. The Azure node.js documentation is really not in good shape and I keep searching for good example on how to do simple things. Pretty annoying and time consuming.
The SDK documentation on delete operations says it works the same way as read, but that is not true. Or I am dumb as a wet door. My code for deleting looks like this - it results in exception
query = queries.create('MyfUserInfo')
.where({ id: results[i].id });
userTable.delete(query).then( function(delet){
console.log("deleted id ", delet);
});
I have also tried this and no success either
userTable.where({ id: item.id }).read()
.then( function(results) {
if (results.length > 0)
{
for (var i = 0; i < results.length; i++)
{
userTable.delete(results[i].id);
});
}
}
Can somebody please point me in the right direction on the correct syntax for this and explain why it has to be so difficult doing basic stuff here ;-) It seems like there are many ways of doing the exact same thing, which really confuses me.
Thanks alot
Martin

You could issue SQL in your api
var api = {
get: (request, response, next) => {
var query = {
sql: 'UPDATE TodoItem SET complete=#completed',
parameters: [
{ name: 'completed', value: request.params.completed }
]
};
request.azureMobile.data.execute(query)
.then(function (results) {
response.json(results);
});
}};
module.exports = api;
That is from their sample on GitHub
Here is the full list of samples to take a look at

Why are you doing a custom API for a table? Just define the table within the tables directory and add any custom authorization / authentication.

Related

Get all Items using the Query API through AWS Amplify

How can we get all the items by invoking dynamodb.query?
The documentation states that we need to look for the presence of LastEvaluatedKey. Just wondering how we could aggregate all the Items in an efficient way?
app.get(path, function (req, res) {
var allItems = [];
var params = {
TableName: tableName,
"IndexName": "status-index",
"KeyConditionExpression": "#attrib_name = :attrib_value",
"ExpressionAttributeNames": { "#attrib_name": "status" },
"ExpressionAttributeValues": { ":attrib_value": req.query.status },
"ScanIndexForward": false
};
dynamodb.query(params, onQuery);
function onQuery(err, data) {
if (err) {
res.json({ error: 'Could not load items: ' + err });
} else {
// Should I be aggregating all the items like this?
allItems = allItems.concat(data.Items);
// Then should I set it to res like this to return all the items?
res.json(allItems);
if (typeof data.LastEvaluatedKey != 'undefined') {
params.ExclusiveStartKey = data.LastEvaluatedKey;
dynamodb.query(params, onQuery);
}
}
}
});
Please look at comments within the code. That is where I think we need to have the appropriate code to aggregate all the items and return back the response.
I have not found a way to debug this yet as I'm fairly new to DynamoDB and AWS Amplify. Let me as well know if there is an easier way to debug this in an AWS amplify backed up GET API.
This is not a direct answer to you question, but a suggestion. I wrote an article "How To Use AWS AppSync in Lambda Functions
".
The TLDR of it is:
Create a Lambda function, which uses the AppSync client to perform
GraphQL operations. Use polyfills and install all necessary
dependencies.
Ensure the Lambda function has the right execution policy.
Use AppSync’s multi auth to allow both requests that are signed by
Amazon Cognito User Pools as well as requests that are signed using
Amazon’s IAM. This way, both the client and the server (aka. the
Lambda function) will be authenticated and can have different CRUD
permissions.
If I were you and wanted to access my data base through a Lambda function, I would follow that tutorial and do it using AppSync. One of the advantages which matters to you is that you don't have to care about LastEvaluatedKey and you can instead use AppSync's nextToken which is way more safe.
Query returns paginated results - if you want all data then you need to keep querying and aggregating until your LastEvaluatedKey is empty.
Refer: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html

MEAN stack: Wondering api.js and crud.js

I'm studying MEAN stack these day, So I make some sample apps following guidance. I made up "Bookshelf" application just few hours ago, this is provided by google cloud service, so I should delve into sample code to understand how it works.
Whole source code : https://github.com/GoogleCloudPlatform/nodejs-getting-started/tree/master/2-structured-data
Sample application : http://mymongo-1165.appspot.com/books
books/api.js
router.get('/', function list(req, res) {
model.list(10, req.query.pageToken,
function(err, entities, cursor) {
if (err) { return handleRpcError(err, res); }
res.json({
items: entities,
nextPageToken: cursor
});
});
});
books/curd.js
router.get('/', function list(req, res) {
model.list(10, req.query.pageToken,
function(err, entities, cursor) {
if (err) { return handleRpcError(err, res); }
res.render('books/list.jade', {
books: entities,
nextPageToken: cursor
});
}
);
});
these 2 codes are similar, but I don't know why these similar codes comes up. I think crud.js enough, but why api.js comes up. Could you explain how these 2 codes work?
In this sample application, there are two interface:
graphic user interface (GUI) - curd.js handles generating HTML that is rendered later in the browser (in our case jade tempting language is involved)
application programming interface (API) - api.js provides the way to interact with application programmatically, without browser (ex: create new record in database, or query some data by making specific call to particular route)
For deeper understanding I would suggest learning more about express.js, that will give better idea what those outputs are.
P.S. Welcome to MEAN world :)

Angular UI Client Side Pagination

I would like to enable pagination and I'm torn between client side and server side pagination. In the long term (more data) it is probably better to do server side pagination, but I haven't found a good tutorial on it.
I use Angular/Express/Mongo. I have the Boostrap UI in use, and would like to use their pagination directive for pagination. I have read some articels on how to kind of do it, but they are outdated and I cannot get it to work. http://fdietz.github.io/recipes-with-angular-js/common-user-interface-patterns/paginating-through-client-side-data.html
Could anybody help me get that example to work with Bootstrap UI for Angular?
If you have a set number of items per page, you could do it this way :
Define an angular service to query the data on your server.
.factory('YourPaginationService', ['$resource',
function($resource) {
return $resource('baseUrl/page/:pageNo', {
pageNo: '#pageNo'
});
}
]);
Call it via the angular controller. Don't forget to inject your service, either globally or in the controller.
$scope.paginationController = function($scope, YourPaginationService) {
$scope.currentPage = 1;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
YourPaginationService.query({
pageNo: '$scope.currentPage'
});
};
};
On express 4 (if you have it), set up your route.
app.route('/articles/page/:pageNo')
.get(data.listWithPagination) //random function name
Then you need to wire that function with the desired Mongo request in your Node controller. If you have Mongoose, it works like this :
exports.listWithPagination = function(req, res) {
var pageLimit = x; //Your hardcoded page limit
var skipValue = req.params.pageNo*pageLimit;
YourModel.find() //Your Mongoose model here, if you use Mongoose.
.skip(skipValue)
.limit(pageLimit)
.exec(function(err, data) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(data);
}
});
};
That's how I would do it on a typical MEAN stack. If you're working with different libraries/technologies, you might need to adapt a few things.

Retrieving album/playlist information API

I read in another thread (http://stackoverflow.com/questions/9474011/showing-a-album-cover)
that the:
Please don't use any of the sp. APIs - they're private and going away soon.
My question is, what is the correct way of getting album and/or playlist information from the API?
I'm currently playing around with this:
sp.core.getMetadata(uri, {
onSuccess: function(uri) {
// Success
},
onFailure: function() {
// Failure
}
});
I guess this is private and shouldn't be used right? Instead I should get the info from the models.* object? If not, is there another preferred method of dealing with this?
Always use models. Documentation can be found here.
For example:
var sp = getSpotifyApi(1);
var models = sp.require('sp://import/scripts/api/models');
var a = models.Album.fromURI("spotify:album:5zyS3GEyL1FmDWgVXxUvj7", function(album) {
console.log("Album loaded", album.name);
});

Playlist null value return

I'm still developping a Spotify App, but I thinkg there is some bug in the API and they report it as a bug for me.
I make then the test with the tutorial app using the function "Get songs from a playlist URL", they are in the tutorial using also the callback function like this
var pl = models.Playlist.fromURI(playlist_url, function(playlist)
But even using the Callback function on first load there is some null value.
With my own playlist, I don't have the issue but with playlist from other users I got the issue.
Does anybody else get the issue ? Is there a way to report API bug ?
For those who want to test my playlist: http://open.spotify.com/user/gpsnail/playlist/6qhk1FhYKwyanNAu91GftW
The Spotify Apps API 0.X is not longer supported. It might be the case that there was a bug and the data was being rendered before it was actually fetched. I would recommend you to use the newer version of the API, in which you can fetch the contents of a playlist doing:
require(['$api/models'], function(models) {
var playlistURI = 'spotify:user:gpsnail:playlist:6qhk1FhYKwyanNAu91GftW';
models.Playlist.fromURI(playlistURI)
.load('tracks')
.done(function(p) {
p.tracks.snapshot()
.done(
function(snapshot) {
for (var i = 0, l = snapshot.length; i < l; i++) {
var track = snapshot.get(i);
// we print out some basic data from the track
console.log(track.uri, track.name);
}
})
.fail(
function(){
console.error('Error retrieving snapshot');
});
})
.fail(function(){
console.error('Error retrieving playlist information');
});
});
There is more information about how to upgrade to the upgrade guide.

Resources