Cosmos DB Javascript stored procedure - bug? - javascript

I've been observing some strange behaviour in a stored procedure in Azure Cosmos DB using javascript API (https://learn.microsoft.com/en-us/azure/cosmos-db/programming#javascript-language-integrated-query-api)
Assuming there is a document in the database with the body.id = '---' the procedure below correctly return that document. However, if I comment the line 'return found ' and uncomment the lines with 'if (1==1)' then the stored procedure returns an empty result. I tried changing it to if (found){return found;} else{return false;}' - same empty output. Also, same happens if I write 'found = found && (1==1);' after 'let found = c.body.id != null && c.body.id ==t;'
Is this a Javascript bug or me doing something wrong?
// SAMPLE STORED PROCEDURE
function sample() {
__.filter(c=>{
//return true;
let t = "---";
let found = c.body.id != null && c.body.id ==t;
return found; <---
//if (1==1){
// return found;
//}
}
, {pageSize: -1},
(a, b, c)=>{
__.response.setBody(b);
return;
});
}

I reproduce your issue on my side.
The following JavaScript constructs do not get optimized for Azure
Cosmos DB indices:
Control flow (for example, if, for, while) Function calls
Based on the statement in the doc, if is not recommanded to use in predicateFunction.
You could just filter documents by return expression(e.g. x.isMetadata === true);

Related

cli input parsing for node.js

i am trying to make a CLIish server in node.js.
but I need a way to parse a string and run a function from an object.
what I mean is... I don't want to nest a million switch statements just to have the commands I need.
using 2 other StackOverflow answers, I got 1 part done. inputs.
now i just need to figure out how to figure ou where the command stops and the input begins.
example:
inputting do say user:Yimmee msg:"well hello" "something random":yes
I need to separate do say and the inputs.
this is what i started with, but I do not know how to finish it.
function command(command, usable){
//usable is the object holding the commands that can be used.
//here I set commandMain to the part of command that is the command
/*and where commandInput is too. and I'm not forcing you,
but is preferably to be converted to an object.*/
var commandSplit = [];
do{
var match = (/[^ "]+|"([^"]*)"/gim).exec(commandMain);
if(match != null){
commandSplit.push(match[1] ? match[1] : match[0]);
}
}while (match != null);
var reach = `usable`;
commandSplit.forEach((to, nu)=>{
if(nu === commandSplit.length - 1){
reach += `["_${to}"]`;
}else{
reach += `["${to}"]`;
}
});
console.log(reach);
try{
return eval(reach)(commandInputs);
}catch(error){
return false;
}
}
Note I gave up a little, there will be some ridiculous errors.
big fat edit::::::::::::::::::::::L:::::::
idk how in the world process.argv works, and looking in one of the answers, i know how to set it.
but i am using a live websocket for this.
Unless this is an exercise, I'd strongly recommend not to implement your own command and argument parser. Use one of the existing libraries. A quick web search for "node cli library" yields a lot of results, including comparisons.
The libraries range from tiny and simple like minimist, very popular ones like yargs or commander, to heavier ones like oclif.
I'd also recommend checking the Command-line utilities section of Sindre Sorhus' Awesome Node.js list.
What you are doing is passing options and arguments to a program. You can use process.argv to get these.
It's always good to have useful error messages and command line documentation. Hence, if you're distributing to users, a more robust library for this purpose is worth an extra dependency. Widely used is yargs, see their website at https://www.npmjs.com/package/yargs for some examples.
If you want to do it using the basic process.argv, here's a solution:
This is your command in a format most people are used to: node some.js --user Yimmee --msg "well hello" --random
And the implementation
let arguments = process.argv.slice(2); // this removes `node` and the filename from arguments list
console.log(arguments)
switch (arguments[0]) { // check that `say` is the first "command"
case 'say':
let options = process.argv.slice(3); // get the stuff after `say`
let optionsObject = {} // key-value representation
if (options.indexOf("--user") != -1) { // if it exists
optionsObject.user = options[options.indexOf("--user")+1]
}
else {
// you can throw an error here
}
if (options.indexOf("--msg") != -1) { // if it exists
optionsObject.msg = options[options.indexOf("--msg")+1]
}
if (options.indexOf("--random") != -1) { // if it exists
optionsObject.random = true
}
console.log(optionsObject) // you can use optionsObject for your program
break;
default:
console.log("Invalid command");
}
EDIT: If this is happening inside the code as a function call, you can adapt above code:
function test(argsString) {
let arguments = argsString.split(/ (?=(?:(?:[^"]*"){2})*[^"]*$)/); // split the string into an array at the spaces
// ^ regex from https://stackoverflow.com/questions/23582276/
console.log(arguments)
switch (arguments[0]) { // check that `say` is the first "command"
case 'say':
let options = arguments.slice(1); // get the stuff after `say`
let optionsObject = {} // key-value representation
if (options.indexOf("--user") != -1) { // if it exists
optionsObject.user = options[options.indexOf("--user") + 1]
}
else {
// you can throw an error here
}
if (options.indexOf("--msg") != -1) { // if it exists
optionsObject.msg = options[options.indexOf("--msg") + 1]
}
if (options.indexOf("--random") != -1) { // if it exists
optionsObject.random = true
}
console.log(optionsObject) // you can use optionsObject for your program
break;
default:
console.log("Invalid command");
}
}

How to get the JavaScript Object from the given string?

How to get the Object from a string?
I written a localStorage util, in it there are get and set methods.
in the set method:
function fnGet(name){
var getVal=storage.getItem(name);
if(getVal==null){
return console.log('the localstorage did\'t have'+name);
}
if((getVal.split(':-:')).lenght>1){
return eval('('+getVal.split(':-:')[0]+')');
}
return getVal.split(':-:')[0];
}
You can ignore the :-:, it is the separator of the saved data and timestamp.
there is a problem, if the data is stored a JavaScript Object, such like this:
'{"pk":1,"username":"test01","email":"","first_name":"","last_name":""}:-:1521381469910'
when I use the get method, it will become like this:
'{"pk":1,"username":"test01","email":"","first_name":"","last_name":""}'
How can I get to the JavaScript Object?
How to optimize my get method?
JSON.parse on your response from the store. localStorage stores everything as strings so you would need to stringify the object at first, as Im supposed you do as otherwise you wouldnt have been able to save it to the store.
Then to retrieve it you would need to parse it to get the javascript object again.
Two things:
Use JSON.parse() instead of eval; it's not only safer, but more descriptive as to what your intent is. Note: this requires using JSON.stringify() on the data being saved in localStorage
Correct your spelling errors; you would never get to the eval/parser block because your length was spelled "lenght"
function fnGet(name) {
let getVal = storage.getItem(name)
if (getVal == null) {
return console.log(`the localstorage did't have: ${name}`);
}
let val = getVal.split(':-:'); // for performance cache the split
if (val.length > 1) { // Spelling error: "lenght" -> length
return JSON.parse(val[0]);
}
return val[0];
}
LocalStorage saves the data stringified. So you should use JSON.parse(yourVariable) to get the data back as JSON
function fnGet(name) {
var getVal = storage.getItem(name);
if (getVal == null) {
return console.log('the localstorage did\'t have' + name);
}
if ((getVal.split(':-:')).lenght > 1) {
return eval('(' + JSON.parse(getVal.split(':-:')[0]) + ')');
}
return getVal.split(':-:')[0];
}
all you needed was JSON.parse which takes a string as an argument and if its a valid object string ,returns an object else throws an error

Proper way to manage paging and search/filter on a REST API made with Node and Express

I am playing around with Node and Express. My current problem is not "how to do things", as I have my paging and filtering/searching working in my "mini API" that I have made from scratch and that I am playing with. My question is more about "good practices" and "proper way" of doing things.
I will put some snippets of code below, which I am sure will bring some critics. The API is memory based, no database involved. I have an array of hard-coded users that I am pulling data from and pushing data in.
Below is my code (as you can see, I have also implemented basic authentication using passport):
//This array contains all my user data...
var users = [
{
"id": "1",
"firstName": "john",
"lastName": "doe"
}
];
//This is the route I have configured in order to retrieve all users.
//I am retrieving the users with the getUsers() function and then returning it.
//in the response object.
router.get('/users', passport.authenticate('basic', { session: false }),
function(req, res, next) {
var result = users.getUsers(req);
res.status(200).json({ users: result });
});
//This method will get the page and items parameters and will try to parse
//them. After that, it will call the search function that will filter the data
//Finally, I am passing the result array, page param and items param to the
//sliceUsers() function that will take care of slicing the result array depending
//on the values of page and items.
exports.getUsers = function(req) {
console.log(req.query);
var page = req.query.page;
items = req.query.items;
page = page !== 'undefined' ? parseInt(page, 10) : undefined;
items = items !== 'undefined' ? parseInt(items, 10) : undefined;
//The search method will filter the data
var searchResults = exports.search(req.query);
//Then, I call sliceUsers(), passing the filtered data, page and items parameters
return exports.sliceUsers(searchResults , page, items);
}
//This method will slice the array to return the page and # of items specified
//The "data" array that is passed as the first parameters is the array that contains
//the data that have already been filtered.
exports.sliceUsers= function(data, page, items) {
page = (page < 1 ? 1 : page) || 1;
items = (items < 1 ? 5 : items) || 5;
console.log('page', page, 'items', items);
var indexStart, indexEnd;
indexStart = (page - 1) * items;
indexEnd = indexStart + items;
return data.slice(indexStart, indexEnd);
};
//Those 2 methods take care of filtering
exports.search = function(query) {
return users.filter(search(query));
}
function search(query) {
console.log('search function');
return function(element) {
for(var i in query) {
//Please note here how I am checking the the parameter I am currently
//checking is NOT 'page' nor 'items'
if(query[i] != element[i] && i !== 'page' && i !== 'items') {
return false;
}
}
return true;
}
}
A few questions arise here:
Is the way I am dealing with filter/search and THEN, dealing with paging the right way?
In the search() function, when I am looping over req.query, I know that the way I check if the current param is different than 'page' or 'items' is not very efficient, but I don't know I could do that differently.
My goal here is to learn node and express and get better at javascript, what would you advice me to do next in order to pursue that goal? Any resources greatly appreciated, as the only stuff I found on APIs are basic operations that don't really deal with search/filtering. When I do find those, it's never in addition to paging for example. I have never found a complete example.
I have heard that underscore could help me do the filtering, but once again, did not really find any good example, any snippets somewhere?
Any critic GREATLY appreciated.
P.S: I apologize in advance for any grammatical error in this question.
There's a standard called OData for thing like filtering, searching, selecting and of course REST. There are few options for using it at the moment. For node backend part it's node-odata. For more, see here: http://www.odata.org/libraries/

How to filter out usercreated events in fullcalendar

I have a fullcalendar where I display non-editable events which are collected from a google calendar, or from a database. Then I want to register customer requests for events from the calendar. This works, but I am not able to list only the events that are added by the user.
Any hint on how to do this?
I tried this:
function retrieve_events() {
var rdv=$('#calendar').fullCalendar( 'clientEvents', undefined);
for (i=0; i<=rdv.length-1; i++) {
/*alert(rdv.toSource());*/
alert(rdv[i].title+" id: "+rdv[i].id+" start: "+rdv[i].start+" end:"+rdv[i].end+" heldag:"+rdv[i].allDay);
}
}
The the "undefined" as id, means that I have given all the non-editable events an id, while the new ones haven't got one. But this way I get all events listed, even those without an id. The same happens with null and ''. But using hardcoded id-numbers returns that specific event.
I see from the documentation that there seems to be other ways to get hold of the events I need, by using other criteria like classes. However I cannot figure out how to specify this filter.
I haven't worked with FullCalendar yet nor do I intend to extensively test this, so I cannot guarantee that this will work.
However, why don't you simple test whether rdv[i].id evaluates to false?
Try:
function retrieve_events( ) {
var rdv = $('#calendar').fullCalendar('clientEvents'),
results = [];
for( var i = 0; i < rdv.length; ++i ) {
if( !rdv[i].id ) {
results.push(rdv[i]);
}
}
return results;
}
P.S.: Passing undefined to .fullCalendar() probably is redundant. It would be equivalent to passing only a single variable. I'd guess the second parameter is a type of events that you can filter for, but passing only a single parameter would cause the plugin to return all events. Also, note that !!'' === false.
The internal check whether the second parameter is set is probably similar to this:
$.fn.fullCalendar = function( command ) {
switch( command ) {
// ... some case's
case 'clientEvents':
var filter = arguments[1];
if( !filter ) {
// Retrieve ALL client events
}
else {
// Filter client events
}
break;
// ... some more case's
}
};
This does not compare types. Testing filter === false would only return true, if filter would evaluate to false and is a boolean.
Following are examples of values that evaluate to false. There may be more, but I believe those are all.
undefined
null
0
false
''

Script debugger confirms intended conditional check between JSON key and string, however I am getting an undesired result?

I am looking to modify the output table I am getting from this handy Json-to-HTML-Table script I stumbled upon here on SO. There is a point (line 86) where json-to-table.js passes a JSON object and generates array keys to be used as table headers. Optionally, this array_key function can generate only one key for a specified search_value parameter passed. I however [attempted] to modify it so that ALL array keys that did NOT match the search_value would be returned. Here is the function after my changes:
function array_keys(input, search_value, argStrict)
{
var search = typeof search_value !== 'undefined', tmp_arr = [], strict = !!argStrict, include = '', key = '';
if (input && typeof input === 'object' && input.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
return input.keys(search_value, argStrict);
}
for (key in input)
{
if (input.hasOwnProperty(key))
{
include = false;
if (search)
{
if (strict && input[key] == search_value)
include = false;
else if (input[key] == search_value)
include = false;
else
include = true;
}
if (include)
tmp_arr[tmp_arr.length] = key;
}
}
return tmp_arr;
}
Now, the reason I did this is because I want my generated table to not include a specific column from my JSON object:
{
"examItemCategories": [
{
"catgoryName": "01-Normal processes",
"catgoryPath": "General Area\\01-Normal processes",
"numberOfItems": 2,
"percentage": "6.06"
}
]
}
Given that I can not modify the original JSON obj passed, I was determining whether or not to attempt to modify the table post creation (e.g. remove column), or during. After looking at the array_keys function, I felt I could easily invert the conditional checking for the search_value.
I now call array_keys(parsedJson[0], 'catgoryPath'); from json-to-table script. (Yes, catgoryPath is the correctly spelled name haha). Then I set a break point at the for loop within array_keys function to follow it through in Firebug.
First iteration: catgoryName is added to tmp_arr, 2nd iteration: catgoryPath is added to tmp_arr...and continues through 3rd and 4th iterations. I do not wantcatgoryPath added.
Looking at script debugger, on the 2nd iteration, whether or not catgoryPath gets added comes down to the conditional: else if (input[key] == search_value) line. The thing is, on the respective iteration both key and search_value variables equal "catgoryPath" according to Firebug. So therefore, include = false; should fire correct?
Any help is appreciated, apologies for the length and liberal usage of inline code.
Instead of using the array_keys function from the json-to-table script, if you are using JS > 1.8.5 you can use Object.keys(obj) to return an array of a given object's own enumerable properties.
The returned array of keys are then used as table headers under which the table populates with JSON data thanks to the script. Prior to the creation of table, I took my array of table headers and used array.splice(index, howMany) instead of delete (see here) to preserve my array index values.

Categories

Resources