Client side mongodb-like queries in backbone - javascript

Is there a way to check whether an object is matched by a mongodb-type query on the client side? For instance:
function is_matched(obj,query){
...something magic here...
}
var potato = {val:1}
is_matched(potato,{val:1})
returns true, and
is_matched(potato,{foo:bar})
returns false.
The tricky part is that I'd like for it to take the same kinds of queries as mongodb so that you can do more complicated things like regular expressions and the like. Is there something on the client side that will emulate mongo's query matching behavior?

I would suggest using Loki.js http://lokijs.org/#/ it is an in-memory no-sql database with a mongodb like query syntax (it works on browser as well)
and here's how your current example can be mimicked using loki.js :
db = new loki('loki.json')
children = db.addCollection('children')
children.add({val: 1})
children.find({val: 1}) // returns [{val: 1}]
children.find({foo: "bar"}) // returns [] (empty collection)

Related

Error: credentials argument needs to implement signRequest method?

When I get the Azure Credentials using "ms-rest-azure" library.
let credentials = await msRestAzure.loginWithServicePrincipalSecret(id, secret, tanent);
let newCred = JSON.stringify(credentials);
let duplicateCred = JSON.parse(newCred); // Create duplicate credentials object
Now if I going to use the "duplicateCred" for my further Azure function call, then I'll get the above error.
But if I'm using "credentials", then all is well.
So how to I assign the "credentials" object to other variable? So that i'll use the variable for my future azure API call.
Example:
let credentials = await msRestAzure.loginWithServicePrincipalSecret(id, secret, tanent);
let newCred = JSON.stringify(credentials);
let duplicateCred = JSON.parse(newCred); // Create duplicate credentials object
// Okay, here I'm getting the proper client object. Because I am using "credentials" in the below line of code.
// I'm getting the results from the below lines of code.
const client = new MonitorManagementClient(credentials, subscription);
const results = await client.operations.list();
context.log('results==> ', results);
// Error, here not getting the proper client object. Because I am using "duplicateCred" as credentials in the below line of code.
// I'm not getting the results from the below lines of code.
// At the below line I'm getting the above error.
const client = new MonitorManagementClient(duplicateCred, subscription);
const results = await client.operations.list();
context.log('results==> ', results);
How do I create a duplicate credential object from actual credentials object ?
This is incorrect method to do so. Credentials returned by msRestAzure.loginWithServicePrincipalSecret call is not a plain object it's an instance of ApplicationTokenCredentials. When you call JSON.stringify you loose this class reference and convert the whole value to Object. So cloned credentials object looses prototype chain with ApplicationTokenCredentials methods.
Also ApplicationTokenCredentials has no cloning logic what could mean it shouldn't be cloned. Using your own cloning logic could conflict with future versions of Azure library. It's better to add an issue in the official Azure SDK repository if you need to have a cloning method.
Note! ⚠️ Such way of cloning could be dangerous and leads to unexpected behaviour. You should strongly avoid it, except of cases when you really need to erase value's prototype chain!

Object behaviour changed after assigned the variable

I have received a query/argument (matchQuery) from the client side through API.
When I console this request.query.matchQuery.on the server side it gives me {"count":{"$gt":1}} this is good for me.
when I assign this argument on the other variable like this
var aggregateQuery = {
$match: request.query.matchQuery
}
and now I console aggregateQuery its returns
{ '$match': '{"count":{"$gt":1}}' }
its behavior gets changed. But I don't want to single quotes on the right
side.
OUTPUT
{ '$match':{"count":{"$gt":1}}}
OR
{ $match:{"count":{"$gt":1}}}
OR
{ $match:{count:{$gt:1}}}
Best way to correct data that receive in serialized JSON is to parse it. JavaScript has JSON global object for facilitate JSON conversion and applied in application.
in your case evidence shows that request that came from client is like this:
"{\"count\":{\"$gt\":1}}"
but in your framework changed to STRING
typeof('{"count":{"$gt":1}}') ==> 'string'
that is not object
for use request.query.matchQuery as java script object your may convert it to JavaScript Object. for more details refer to below example:
var aggregateQuery = {
$match: JSON.parse(request.query.matchQuery)
}
Notice:
If you are not in STRICT MODE by adding
"use strict"
you can execute your code with
eval( code to be execute )
for examlpe
eval(`var e = { '$match':` + '{"count":{"$gt":1}}' + `}`)

Why can a MongoDb cursor be indexed as if it was an array?

I noticed that if I execute a JavaScript script using the mongo command, the script can treat a cursor object as if it was an array.
var conn = new Mongo('localhost:27017');
var db = conn.getDB('learn');
db.test.remove({});
db.test.insert({foo: 'bar'});
var cur = db.test.find();
print(cur[0].foo); //prints: bar
print(cur[1]); // prints: undefined
This seems like it should be beyond the capabilities of the JavaScript language, since there is no way to "overload the subscript operator". So how does this actually work?
As documentation says, it is special ability of driver. It automagicly converts cursor[0] to cursor.toArray()[0]. You can prove it by overriding toArray() with print function or new Error().stack to get callstack back. Here it is:
at DBQuery.a.toArray ((shell):1:32)
at DBQuery.arrayAccess (src/mongo/shell/query.js:290:17)
at (shell):1:2
As you can see, indexing calls arrayAccess. How? Here we have a dbQueryIndexAccess function, which calls arrayAccess.
v8::Handle<v8::Value> arrayAccess = info.This()->GetPrototype()->ToObject()->Get(
v8::String::New("arrayAccess"));
...
v8::Handle<v8::Function> f = arrayAccess.As<v8::Function>();
...
return f->Call(info.This(), 1, argv);
And here we have a code, which sets indexed property handler to this function. WOW, v8 API gives us ability to add this handler!
DBQueryFT()->InstanceTemplate()->SetIndexedPropertyHandler(dbQueryIndexAccess);
... and injects it into JS cursor class, which is defined originaly in JS.
injectV8Function("DBQuery", DBQueryFT(), _global);
Tl;dr: It is hacked in C++ source code of mongo shell.

FindMany overwritten doesn't work. Ember-data

In my project, if I ask my server for the records with id 1,2,3 like this (without spaces):
url?sites=id1 %2C id2 %2C id3
It will return a json file with the records for this ids.
So for this case I think I can have then cached if I manage to use findMany and make the RestAdapter make the call to the server in this way.
I have found the next, but it doesnt work, it continues calling:
GET topologymins/1,2
Adapter:
App.ApplicationAdapter = DS.RESTAdapter.extend({
findMany: function(store, type, ids) {
Ember.Logger.log("INSIDE THE findMany"); // NOT SHOWED
var url = type.url;
url = url.fmt(ids.join(','));
jQuery.getJSON(url, function(data) {
// data is an Array of Hashes in the same order as the original
// Array of IDs. If your server returns a root, simply do something
// like:
// store.loadMany(type, ids, data.people)
//store.loadMany(type, ids, data);
});
}
});
App.Topologymin.reopenClass({
url: '/something?ids=%#'
});
My call:
this.store.find('topologymin',[1, 2]);
Isn't this just because you're missing a return?
Oh... sorry your findMany isn't written correctly, I don't htink... it's missing a return... but that isn't actually what's wrong - it's not even calling the findMany because store.find() can't be passed an array of ids... you want this, I think: store.find('topologymin', { ids: [1,2] });
However, I think you'll have another problem in that findMany should have a return value in it... if you look at the default implementation, you'll see what I mean... it needs to return a promise, and you're not returning anything.

Store and retrieve Google Dart objects in JavaScript library containers

Store and retrieve Google Dart objects in JavaScript library containers
In a Dart application I am using an external JavaScript library to do various matrix calculations.
The specific functionality of the library is not important, what it's important is that I need to store and retrieve Dart object that I put in the matrix.
Dart Class - Lets image i have a dart object that which has a parameter called name
MyDartClass mydc = new MyDartClass(something, something);
mydc.name;
// Everything works as planned
Storing
matrix = js.context.matrix
matrix.cell(1,1).store("thing", new MyDartClass(something, something));
Retrieving
matrix.cell(1,1).has_object_of_type("thing");
// true
MyDartClass mydc = matrix.cell(1,1).retrieve("thing");
Do something with the object
mydc.name;
// Exception: The null object does not have a getter 'name'.
// NoSuchMethodError : method not found: 'name'
// Receiver: null
// Arguments: []
Does the library really work?
Yes it does. I have done the exact same thing in pure javascript many times and there are plenty of test to test the behaviour ( in Javascript )
Is Dart Broken?
When I try to use a javascriptified Hash to do the same behavoiur it works like a charm.
var options = js.map({ 'dart' : new MyDartclass(something, something));
var y = options["dart"];
js.context.console.log(y.name);
// Name is printed
What do you get out from the retrieve?
It seems that I get some kind of Dart Proxy
MyDartClass mydc = matrix.cell(1,1). retrieve("thing");
js.context.console.log(mydc);
DartProxy {id: "dart-ref-20", port: DartSendPortSync}
id: "dart-ref-20"
port: DartSendPortSync
__proto__: DartProxy
I belive that the lib stores the objects, deep down, in a hash map. But it seems like when I retrieve the object into the Dart I get something, but not in a way that I can work with it. So i need help since I don't know how to make it work.
Do I need to de-proxify the object?
Perhaps it IS a Dart bug when you try to retrieve objects from hashes inside objects
Perhaps I missunderstod everything that this is not suppose to work.
Passing and retrieving Dart objects inside the same scope is working. There's the following test case in the tests of js-interop to proove it :
test('retrieve same dart Object', () {
final date = new DateTime.now();
js.context.dartDate = date;
expect(js.context.dartDate, equals(date));
});
However there seems to be an issue with multiple scopes (and multiple event loops as well). There is no way to retain a dart object for now. So your dart object reference goes away at the end of scope. Here's a simple test case that fails :
test('retrieve same dart Object', () {
final date = new DateTime.now();
js.scoped(() {
js.context.dartDate = date;
});
js.scoped(() {
expect(js.context.dartDate, equals(date));
});
});
Please file an issue.

Categories