Function is not recognized in map reduce command, mongoDB (javascript) - javascript

I have some problems with a map reduce I tried to do in MongoDB. A function I defined seems to not be visible in the reduce function.
This is my code:
function getName(user_id){
var users = db.users.aggregate({$project:{"_id":"$_id", "name":"$name"}});
users.forEach((it) => {if (user_id == it._id) return it.name;});
return "user not found";
}
var mapFunc = function(){ emit(this.user_id, this.book_id) };
var reduceFunc = function(key, values){return getName(key);};
db.booksToRecover.mapReduce(mapFunc, reduceFunc, {out:'users_to_recover_books_from'});
This is what I get:

The function was defined in the locally running javascript instance, not the server.
In order for that function to be callable from the server you will need to either predefine it there or include the definition inside the reduce function.
But don't do that.
From the reduce function documentation:
The reduce function should not access the database, even to perform read operations.
Look at using aggregation with a $lookup stage instead.

Related

Is Mongodb stitch functions can use bulkwrite()?

I try to call collection.bulkWrite() in MongoDB stitch functions, but I get an error - “bulkWrite is not a function”. Is it possible to use bulkWrite() in MongoDB stitch functions?
Here is my stitch function - and I made it “run as a system”:
exports = function(arg){
var collection = context.services.get("mongodb-atlas").db("testDATABASE").collection("allSkuTable");
return collection.bulkWrite(some_paramets_inside);
};
What is the proper way to call bulkWrite() if it is even possible?

Why functions in module are not passed back to the main process?

I need to load untrusted modules, written by third parties. I'm using vm for the sandbox and I was thinking to use threads (from npm: here) in order to load the module asynchronously and avoid blocking code.
I have stripped down the code to the minimum, because I'm stuck and I dont' understand if what I'm trying to achieve is impossible or it's just me messing with scopes.
Here is a dummy module:
exports.dummy = function () {
console.log('Dummy');
};
exports.val = 5;
And here is a module where I try to load this dummy module using threads:
var spawn = require('threads').spawn;
var mod;
var other;
var t = spawn(function (input, done) {
var m = require(input.dir + '/dummyMod');
done({m: m, other: 'hey'})
});
t.send({dir: __dirname}).on('message', function (result) {
mod = result.m;
other = result.other;
console.log(mod);
console.log(other);
t.kill();
});
The logged output is:
{ val: 5 }
hey
As you can see, the function in the dummy module has been skipped. If I try to load the module in the main process and log it, then the function is, of course, part of the object.
You need to properly serialize and deserialize the function. JSON.stringify ignores functions, probably because json is a format for storing data, not scripts.
Serialize the function by calling toString() on it. Then you can send it along as a string.
done({m: m.toString(), other: 'hey'})
Converting m to a string will give you something like this:
"function m(){console.log(\'called m()\')}"
On the receiving end, you will need to deserialize the function.
var m = new Function("return " + result.m)()

Get data out of callbacks

I am using "pdf-text" module for Node.js to convert a pdf into a string array and then get specific elements out of it. But the problem is, I can only access the data, "chunks", only when I am inside the callback. I want to store it in some global variable so that I can use it in different files. I have tried storing the elements of the array inside variables while inside the function, but no luck. Here's the code:
var pdfText = require('pdf-text');
var pathToPdf = "PDF FILE NAME";
var fs = require('fs');
var buffer = fs.readFileSync(pathToPdf);
var output;
pdfText(buffer, function(err, chunks){
if (err){
console.dir(err);
return;
}
console.dir(chunks);
output = chunks;
}
console.dir(output);
P.S. I am fairly new to Node.js and JavaScript and help would be appreciated greatly.
The output variable will only be set with "chunks" contents when the callback is called.
Btw, you need to add ");" after the callback function declaration on the pdfText function call.
var pdfText = require('pdf-text');
var pathToPdf = "PDF FILE NAME";
var fs = require('fs');
var buffer = fs.readFileSync(pathToPdf);
var output;
pdfText(buffer, function(err, chunks){
if (err){
console.log(err);
return;
}
otherFunction(); // undefined
output = chunks;
otherFunction(); // chunks content
});
function otherFunction() {
console.log(output);
}
console.log(output); // undefined
About js callbacks: https://www.tutorialspoint.com/nodejs/nodejs_callbacks_concept.htm
But the problem is, I can only access the data, "chunks", only when I am inside the callback.
Yes, that is correct. You can't access the data before it is available, and when it becomes available, your callback gets called with the data.
I want to store it in some global variable so that I can use it in different files.
Suppose you did this. Now you have a problem. Your code in those different files: how will it know when the data is ready? It won't.
You need some way to tell that code the data is ready. The way you tell that code is by calling a function. And at that point you don't need global variables: when you call the function in that other file, you pass the data to it as a function parameter.
In other words, don't just have global code in some file that expects to be able to use your chunks data by referencing a global variable. Instead, write a function that you can call from your callback, and pass chunks into that function.
If you are using node 8, I believe you can use the async-await feature. So you can refactor your code so that it looks like the following:
var pdfText = require('pdf-text');
var pathToPdf = "PDF FILE NAME";
var fs = require('fs');
var buffer = fs.readFileSync(pathToPdf);
var output;
async function getPDF(buffer) {
pdfText(buffer, function(err, chunks){
if (err){
console.dir(err);
return;
}
return await chunks;
}
}
// you can get the chunks given the buffer here!
console.dir(getPDF(buffer));
I want to store it in some global variable so that I can use it in different files. I have tried storing the elements of the array inside variables while inside the function, but no luck.
I don't think you can store the chunks as a global variable though as you would have to export the chunk (e.g module.exports = getPDF(buffer);), which is synchronous, while the function getPDF is asynchronous. So you have to use it within the same file. What I would do, is import the function instead and then pass it a different buffer in different js files where different pdf is required. Hope this helps.

How to make api request with callback as argument in node.js?

I want to use method getPlayers(callback) which is defined as:
getPlayers(callback)
callback - Required. Called with an object of players
players - An object containing all the players connected to the server, with their name as the key
Retrieve all players connected to the server.
Here is the link to complete module for further details :
https://www.npmjs.com/package/hltv-livescore#getplayerscallback
If you want to use it and access the data, you'll need to do something like this:
getPlayers(function(players) {
// Here your players will be available
console.log(players)
})
Bonus: If you're using ES6, you can use Arrow functions, that are more elegant, like this (single line):
getPlayers(players => console.log(players))
or (multi line):
getPlayers(players => {
console.log(players)
})
You can read more about the async nature of Javascript here
If you refer source code of npm package you can see this code
https://github.com/andrewda/hltv-livescore/blob/master/lib/index.js#L78
Livescore.prototype.getPlayers = function(callback) {
callback(self.players);
};
You can use getPlayers like this :
Livescore.getPlayers(function(players){
// you will get players here
});

How can I invoke a class method in Swift if I only have the string?

I am writing a cordova plugin for HealthKit and my task is to make sure that we can dynamically read more or less data from HK. Im doing the native part in swift. But I mostly write JavaScript so I am a bit lost in with the Swift part.
I want to be able to dynamically invoke methods having only a string.
let store = HKHealthStore()
do {
let bloodType: HKBloodTypeObject = try store.bloodType()
...
That is an example to read blood type. I am not a Swift developer, but is there any way I can do this dynamically, like I would do in javascript:
... // assuming this function receives a string as paramater
let param[0] = try store[param[0]]() // <-- how to do this in Swift?
then i can talk to a server and get a list of characteristics and load them dynamically from healthkit without having to update my code and hardcode for each possible characteristic.
Create a mapping from your parameter strings to an API enumeration.
enum API: String {
case function1 = "function1"
case function2 = "functionTwo"
case function3 = "threethreethree"
}
Create a relay function that maps the API enumeration to the Swift function.
func callTheCorrectFunction(_ api: API) {
switch api {
case .function1: updateBlood()
case .function2: spinAround()
case .function3: jump()
}
}
Construct your function call using enum's rawValue initializer.
let param = fromSomeJsonStrings[0]
let api = API(rawValue: param)
callTheCorrectFunction(api)
Alternatively, you could use a dictionary mapping from [String: Function] in much the same way.
typealias Function = () -> ()
let dict = {
"function1": updateBlood,
"function2": spinAround,
}
dict[param[0]]()

Categories

Resources