Meteor passing MongoDB selector from parameter - javascript

I want to so some query that is as same as LIKE from the good old school rdbms, so I have to use some sort of regex for that.
When I try this, it works fine
Countdowns.find({"name":{ "$regex": /ANW/ }},{ sort: {regDate: -1 }});
the value returns correctly. However when I build the mongoDb selector (the first JSON param for the function) it never works.
var key = Session.get('searchKey');
var field = Session.get('searchField');
var temp = '{"'+ field +'":{ "$regex": /'+key+'/ }}';
var selector = JSON.parse(JSON.stringify(temp));
Countdowns.find(selector,{ sort: {regDate: -1 }});
When i test it out (using try-catch during JSON.parse), the JSON object was built without any error but somehow the function (find()) fails to operate when i pass it as variable.
Is there other way to build the selector?

I have tested on the console and this is what I got.
Try to make it this way
var key = Session.get('key'), field = Session.get('field');
var selector = {};
selector[field] = { $regex : new RegExp(key) };
With this you will get:
And that should be acceptable for minimongo.
Why JSON.parse didn't work? At the point you where passing temp this is what it looked like:
You already had a string before passing it to JSON.stringify. But wait! You would say, if I instead pass it to JSON.parse it will work? Let see:
Nope. The forward slash has to be properly formatted and even then you'll get a string for the $regex, and you want a RegExp object.
So the way one end ups doing this is what I wrote you before. First you define the variable that will hold your selector for the database as an object and with that you construct your selector.

Related

query-string pick method returns the first match from a filter and corrupted URL

I am trying to clean a URL and only keep some parameters that I need in order to parse them
so I was using pick method providing it the url, and the filter which is a regex test method
here I am testing to check if the key in the query parameter matches the regular expression
const groupRegex = new RegExp('^(GRP_)[a-zA-Z0-9/-]','g');
export const parseGroups= (url:string)=>{
let pickedURL = qs.pick(url,(key,value)=>groupRegex.test(key));
console.log(pickedURL);
}
var url=`http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1`
parseGroups(url)
for example http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1
it should return http://localhost:3000/tat?GRP_Bob=SW&GRP_sa=QW&GRP_sa=AA
yet it only tests for the first request parameter only and logs
http://localhost:3000/tat?GRP_Bob%5B%5D=SW
I am trying to clean the url from any other parameters that doesn't match my regular expression
so I can parse the URL and extract the object
so it can be like this for example
{
GRP_Bob:["SW"],
GRP_sa:["QW","AA"]
}
Instead of having other parameters parsed also which are not necessary. I know I can just parse the url normally, and then loop on the returned query object, and remove any key that doesn't match the regex, but is there anything wrong I am doing in the above snippet?
UPDATE:
I changed the filter function to be (key,value)=>key.startsWith('GRP_'))
export const parseGroups= (url:string)=>{
let pickedURL = qs.pick(url,(key,value)=>key.startsWith('GRP_'));
console.log(pickedURL);
let parsedURL = qs.parseUrl(pickedURL)
console.log(parsedURL.query)
}
var url=`http://localhost:3000/tat?GRP_Bob[]=SW&GRP_sa[]=QW&GRP_sa[]=AA&projects[]=MP,PM&releases[]=2021.4,2022.1`
parseGroups(url)
and the pickedURL logged this http://localhost:3000/tat?GRP_Bob%5B%5D=SW&GRP_sa%5B%5D=QW&GRP_sa%5B%5D=AA which is likely to be correct.
it came out like that
GRP_Bob[]: "SW"
GRP_sa[]: (2) ['QW', 'AA']
So I am confused actually what's going on with the regular expression approach, and why the keys in the second approach have [] in it?
Ah yeh! This one is a rare gotcha and totally unexpected every time I see it. RegExp actually has state. See Why does JavaScript's RegExp maintain state between calls? and Why does Javascript's regex.exec() not always return the same value?.
In your case, you don't need the g flag, so removing that should also fix your problem since that makes the regex stateless.

Is there a way to tell whether a function parameter was passed as either a literal or as a variable?

I have a function:
function hello(param){ console.log('param is '+param); }
And two calls. First:
hello(123)
Second:
var a=123; hello(a);
Is there any possible way to tell, from within the hello function, whether param was passed as a var or as a literal value?
NOTICE: I am not trying to solve a problem by this. There are many workarounds of course, I merely wanted to create a nice looking logging function. And also wanted to learn the boundaries of JavaScript. I had this idea, because in JavaScript we have strange and unexpected features, like the ability to obtain function parameter names by calling: function.toString and parsing the text that is returned.
No, primitives like numbers are passed by value in Javascript. The value is copied over for the function, and has no ties to the original.
Edit: How about using an object wrapper to achieve something like this? I'm not sure what you are trying to do exactly.
You could define an array containing objects that you want to keep track of, and check if its in there:
var registry = [] // empty registry
function declareThing(thing){
var arg = { value: thing } // wrap parameter in an object
registry.push(arg) // register object
return arg; //return obj
}
function isRegistered(thingObj){
return (registry.indexOf(thingObj) > -1)
}
var a = declareThing(123);
hello(a);
function hello(param){
console.log(isRegistered(param));
}

How to set a localStorage item as function?

I would like to set a localStorage item as a function, but when I do it gets saved as a string.
localStorage.getData = function (key="def") {
let data = null;
if (this[key] && !_this.isDataAvailableInList(this[key])) {
data = this[key].data;
}
return data;
};
The above function get stored as string and not function.
Note: Kindly do not provide alternatives or other suggestions, I am well aware of alternatives and am curious to know how this works. I have not provided the entire context so lets just assume I am in need of setting a localStorage item as a function
Unfortunately local storage is only about strings. Even arrays or other data are always converted to strings.
For most dead data without cycles you can use of course JSON.stringify and JSON.parse, but in other cases or for code or other Javascript entities unsupported by JSON (like Infinity or undefined) you need to serialize and deserialize yourself.
Javascript provides eval, so you can store the function f converting it first to a string with f+"" and get back the function with eval(s).
This won't work with closures however and moreover you cannot even know if a function is indeed a closure or not in Javascript (so you cannot even raise an error if the impossible operation of serializing a closure is attempted).
Convert the function into a string via .toString(). When you read it, convert it back to a function via new Function(myString).
Example:
No pamameters:
(new Function('var a = 0; return a + 1;'))() === 1
With parameters:
(new Function(['param0'],'var a = param0; return a + 1;'))(100) === 101
Note: The scope of the original function will be lost.

Extracting a URL parameter value in JavaScript

I have the following function (which I didn't write) to extract a URL parameter value:
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ""])[1].replace(/\+/g, '%20')) || null
}
I have virtually no experience with regular expressions. This code currently does a case sensitive search for the parameter name. I'd like to have RegExp do a case insensitive search for the name of the parameter. Could someone show me how I might change this to accomplish that?
Add i flag for regexp(more info):
new RegExp('your regexp', 'i')
Here's something that I've been using that may help, as I need to do something very similar to pull down a substring of the current page's URL to then pass into a variable to be used in several of my functions.
Here's the generic format of my URLs:
file:///Users/myname/folder/teamname.html
And here's what how I'm parsing them:
function parseURL() {
var match = window.location.href.match(/(\w+).html$/);
if (match) {
return match[1];
}
return null;
}
This will do this:
1) Check the URL for the current page
2) Parse the URL into two different fragments of an array: "teamname" and "html"
3) I then return match[1] which is "teamname"
How I'm using it:
From there, I declare a variable for the parseURL function like this:
var teamSched = parseURL();
So now, I can make dynamic calls for any page with the same URL syntax I've outlined above to have specific code executed with the page-specific variable from parseURL(). Then, I use that variable to generate unique datasets from objects in my code who's key match the "team name" variable created by parseURL().
Someone definitely correct me if I'm wrong, but case sensitivity shouldn't be a factor here, as long as the value you're pulling from your URL via parseURL matched the variable, object key, etc. you're trying to access.
I hope that helps!

Javascript arrays and Meteor session

I have made an interesting observation. When trying to update an array that is stored in the Meteor session storage, the following code will not propagate the changes:
var tags = Session.get("Tags");
tags.push("a");
Session.set("Tags", tags);
But if I change the first line to use Session.get("Tags").slice(), everything depending on the session will update accordingly. I guess this is due to the fact that Meteor tests some references for equality and therefore does not update anything.
Is there a better way to manage lists stored in the meteor session store?
If I now try to remove an element from the collection (using array.remove() from here), the behavior turns out to be a bit ... of ... I am doing this inside a Meteor template event, the code looks like this:
"click .taglist li" : function(e) {
var tags = Session.get("Tags").slice();
var index = cardTags.indexOf(this);
Meteor._debug(Session.get("Tags").slice().indexOf("a"));
Meteor._debug("Removing tag \"" + this + "\", index: " + index, ", typeof(this) = " + typeof(this).toString());
tags.remove(index);
Session.set("Tags", tags);
}
This outputs:
1
Removing tag "a", index: -1, typeof(this) = string
So somehow, the cardTags.indexOf(this); statement seems to return -1 for almost any case. I guess I am doing something fundamentally wrong, as I am quite now to javascript, but somehow I can not figure out whats going on here.
Why will those two calls to indexOf() behave different?
I believe this is the same as this situation in Backbone.js. In order for the change event to be triggered, Meteor needs to have a new reference for the array, not just an updated copy of the old one.
In brief, in order to have the 'correct' behaviour, you'll need to clone the array, make the changes you want, and then do Session.set('foo', myCopiedArray).
In short: Use var index = cardTags.indexOf(this.toString()); instead.
Long version:
When using strings in JavaScript, those are strings, whereas typeof 'test' returns string.
Let's take a look at the following code in order to get find out another way to represent strings in JavaScript:
var func = function () {
return this;
};
console.log(func.call('test'));
The console (at least FireBug) won't show us "test", but instead it shows String {0="t", 1="e", 2="s", 3="t" }. typeof would return "object".
The content of the this statement seems to need to be an object. In order to convert a string into a "String" object we can do console.log(new String('test'));, which is the same as the previously logged value.
To convert a string object into a string (data type), just use its prototype toString.

Categories