Overriding delete operation on Azure Mobile Services table - azure

I'd like to override delete operation on my Azure Mobile Services table to make it more like update then real delete. I have additional column named IsDeleted and I'd like to set it's value to true when delete operation is executed.
I figured out, that what I need is:
fire my own 'update' inside del function,
delete current request.execute()
prepare and sent response by myself
That meens my del function should look like that:
function del(id, user, request) {
// execute update query to set 'isDeleted' - true
// return standard response
request.respond();
}
As you can see I'm missing the first part of the function - the update one. Could you help me writing it? I read Mobile Services server script reference but there is no info about making additional queries inside a server script function.

There are basically two ways to do that - using the tables object, and using the mssql object. The links point to the appropriate reference.
Using mssql (I didn't try it, you may need to update your SQL statement):
function del(id, user, request) {
var sql = 'UPDATE <yourTableName> SET isDeleted = true WHERE id = ?';
mssql.query(sql, [id], {
success: function() {
request.respond(statusCodes.OK);
}
});
}
Using tables (again, only tested in notepad):
function del(id, user, request) {
var table = tables.getTable('YourTableName');
table.where({ id: id }).read({
success: function(items) {
if (items.length === 0) {
request.respond(statusCodes.NOT_FOUND);
} else {
var item = items[0];
item.isDeleted = true;
table.update(item, {
success: function() {
request.respond(statusCodes.OK, item);
}
});
}
}
});
}

There is a Node.js driver for SQL Server that you might want to check out.
The script component of Mobile Services uses node.js. You might want to check out the session from AzureConf called Javascript, meet cloud

Related

Azure stored procedure in Azure portal not working although SQL query works

The following stored procedure failed to produce any result even though the SQL query used in it produced results when tested on the Azure portal.
function checktemp() {
var context = getContext();
var container = context.getCollection();
var response = context.getResponse();
let query = `SELECT DISTINCT {"Elevator": t.connectiondeviceid,
"Vibration": t["vibration"],
"Temperature": t["temperature"]}
FROM t
WHERE t["temperature"] > 75
AND t.EventEnqueuedUtcTime > "2019-08-03T20:30:51.905Z"
ORDER BY t["temperature"] DESC`
// Query documents and take 1st item.
var isAccepted = container.queryDocuments(
container.getSelfLink(), query,
function (err, feed, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) {
response.setBody('no docs found');
}
else {
var body = { moststrain: feed[0] };
response.setBody(JSON.stringify(body));
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
I expect to have items returned, but I always get 'no docs found'. My partition key is /ConnectionDeviceId.
Tested your sample document with your stored procedure code,it works for me.Your SP structure should be fine.
Some mistake with the spell of property(ConnectionDeviceId) you provide,it should be ConnectionDeviceId in sql:t.ConnectionDeviceId.
To solve such issue like something works in the portal, no results in SP, i suggest you removing query statements partially step by step to locate which part of SQL causes no results.
Anyway,the issue is related to partition key. When you query data in the portal, it scans all the partitions. However,if you execute SP,it only scans specific partition.
Since the data is partitioned on 'connectiondeviceid', I was supposed to provide a value of it during execution of the stored procedure.

newbie node.js bot integration with database lookup (looking for best practice)

OK, new to Node.js and botframework. I built first bot using Azure site and downloaded the code. Chose the Luis integrated bot template.
I understand (finally) the event driven model of node.js and the concept of callbacks.
I have the code snippet below. When Luis finds an intent of "Help" it triggers this function. In turn, I have database calls to lookup the entity. Within the database I have an entity, response (if entity is bottle, answer "Recycle").
I have that code working too.
Below the first block is a function handleHelpRequester which is the callback function, I have that working as well. Where I am a little stuck (best practice) is that in this callback function I want to send something to the session object (session.send toward the bottom of the function).
Since I don't create the session object (directly) I'm not sure on the options.
Should I pass the session object to the database function, then pass it back?
Should I create a global variable and set it to the session object (I'm concerned that if multiple people are using this bot then this approach won't work).
I'm open for suggestions.
Thanks
.matches('Help', (session, args) => {
var entities = args.entities;
var itype = builder.EntityRecognizer.findEntity(args.entities, 'ItemTypes');
var respondToUser = '';
var msg = 'Initialized';
// if there is an entity provided, perform a lookup of the entity.
if (itype.entity !== null) {
//Use session.sendTyping so the user thinks something is happening rather than being ignored while we do the lookup in SharePoint.
session.sendTyping();
//perform lookup
respondToUser = sp.lookupEntity(itype.entity, handleHelpRequest);
};
})
function handleHelpRequest(err, respondToUser) {
var msg = 'uninitialized';
if (err = 'success') {
console.log('Respond to user from matches:'.concat(respondToUser));
//return from lookup
if (respondToUser === 'No match found') {
msg = 'I think you are asking for help, but I don\'t understand what you need help with.';
}
else {
msg = 'I can help you with that, \'%s\'.', respondToUser;
}
console.log(msg);
session.send(msg);
//The following two lines are for debugging
session.send('How may I assist you? ' + JSON.stringify(args));
session.send('Value of entity you said: \'%s\'.', itype.entity);
}
else {
console.log('an error occurred');
}
}
If you want to have access to the session object, then pass it as a parameter to your helper function.
Example:
function handleHelpRequest(session, err, respondToUser) {
// do session stuff
}

DocumentDB / CosmosDB - Entity with the specified id does not exist in the system

i tried to connect documentdb from my asp.net website but i am getting this error.
Entity with the specified id does not exist in the system
DocumentClientException: Entity with the specified id does not exist in the system
code as follows in aspx code behind
protected async void Page_Load(object sender, EventArgs e)
{
Response.Write("Page Load<br/>");
await GetData();
}
public async Task GetData()
{
try
{
Response.Write("<br/> Get Data function Start<br/><br/>");
using (var client = new DocumentClient(new Uri(ConfigurationManager.AppSettings["endpoint"]), ConfigurationManager.AppSettings["authKey"]))
{
//await client.OpenAsync();
RequestOptions reqOpt = new RequestOptions { PartitionKey = new PartitionKey(209) };
var parameters = new dynamic[] { 1 };
StoredProcedureResponse<object> result = await client.ExecuteStoredProcedureAsync<object>(
UriFactory.CreateStoredProcedureUri(ConfigurationManager.AppSettings["database"], ConfigurationManager.AppSettings["pcsd"], "GetMemberbyId"), reqOpt, parameters);
Response.Write(result.Response.ToString());
}
Response.Write("<br/><br/> Get Data function End");
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
stored procedure as follows
function GetMemberbyId(memId) {
var collection = getContext().getCollection();
//return getContext().getResponse().setBody('no docs found');
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root m where m.memberId='+memId,
function (err, feed, options) {
if (err) throw err;
// Check the feed and if empty, set the body to 'no docs found',
// else take 1st element from feed
if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
else getContext().getResponse().setBody(feed);
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
in my localhost it's working fine but website published to azure web apps and running i am getting above error
I just spent a couple of hours troubleshooting this, only to find that I had firewalled my instance to a point where I could not connect locally. Keep in mind that the Azure portal document query will obviously still work even when you have no direct access via the API / C# client.
Try setting the firewall to allow All Networks temporarily to check access.
I would check in the portal that the "GetMemberbyId" is the name of the stored procedure for the collection you are trying to run it on. Could be the stored procedure is on a different collection or that the stored procedure is named something else.
If that all checks out.. I have had more luck with the __.filter() way of querying documents on the server. See:
http://azure.github.io/azure-documentdb-js-server/

Azure mobile service table filter

I am trying to get users that are present in array onlineUsers, but it is giving me following error. Can someone please give me work around if this doesn't work
CODE:
exports.post = function(request, response) {
var onlineUsers = ["6990"];
// Tables
var userTable = request.service.tables.getTable('Users');
userTable.where(
function(ou) {
return ou.search(this.id) != -1;
},onlineUsers).read({
success : function(users){
response.send(statusCodes.OK, { message : users });
}
});
};
ERROR:
Error in script '/api/test_find.js'. Error: The expression 'ou.search(this.id)'' is not supported.
Try the following:
userTable.where(function(ou) {
return this.id in ou;
}, onlineUsers)
Keep in mind that the SQL generated contains a separate where clause for each element of onlineUsers, so it can become quite inefficient if the array contains many elements. We're looking at improving the query API.

DocumentDB: Delete a document by ID

I'm using a new database from Microsoft called DocumentDB. Now I want to delete a document by ID, but I cannot figure out, how to do this. Delete operation in DocumentDB requires self-links and they are different from my own ids.
using (var client = new DocumentClient(EndPoint, AuthKey))
{
await client.DeleteDocumentAsync("**self-link here**");
}
I can execute an additional query to find the self-link and then pass it, but this will require two operations instead one and that is what I'd like to avoid. Is there a better way to remove an entry by ID without using queries or stored procedures?
* UPDATE * This feature has now been implemented
* ORIGINAL ANSWER *
Not today, no. You can head to http://feedback.azure.com/forums/263030-documentdb and vote for the feature there.
Here is how I am deleting document
{
var docUri = UriFactory.CreateDocumentUri(_documentDataBaseId, _documentCollectionId, docId);
await _documentClient.DeleteDocumentAsync(docUri);
}
This features has now been implement (as of the 8/2015 - https://feedback.azure.com/forums/263030-documentdb/suggestions/6333050-it-should-be-possible-to-remove-a-document-by-id
as there's no solution for this case I'd recommend to retrieve all the documents in the existing collection to get access to the SelfLink and _rid values.
I just started a mini wrapper to get access to DocumentDB in Universal Apps and hopefully CrossPlatform using Xamarin: https://github.com/JorgeCupi/documentDB-Win10UAP-wrapper feel free to give me any feedback, participate or request some needed methods.
I have tried this code in nodejs to deletebyId and it works for me.
deleteDocumentById: function(params, callback) {
var self = this,
query= params.query,
collection = params.collection;
client.queryDocuments(collection._self, query, function(err, docs) {
if (err) {
return callback(err);
}
client.deleteDocument(docs[0]._self, docs[0], function(err, success) {
if (err) {
return callback(err);
}
callback(null, success);
});
});
}
I was continuously receiving this error: Microsoft.Azure.Documents.DocumentClientException:
Entity with the specified id does not exist in the system.,
The main trick of deleting is PartionKey id. You suppose inside PartionKey provide id
like in the code example.
I have tried many ways, but I was always receiving different errors...Only this solution worked for me.
await client.DeleteDocumentAsync(input[0].SelfLink,
new RequestOptions
{
PartitionKey = new PartitionKey(input[0].Id)
});
Hope this helps :)

Resources