问题
I deployed a nodejs app on appcloud with mongodb as service, I would like to use mapReduce for some queries but I got this error:
2016-10-21 15:45:52 [APP/0] ERR ERR! { [MongoError: cannot run map reduce without the js engine]
Is it supported on swisscom appcloud or what?
This is my controller (an extract):
'use strict';
const mongo = require('../mongoclient');
const paramsParser = require('../paramsParser');
const log = require('npmlog');
const faker = require('faker');
const _ = require('lodash');
const datapoints = function (router) {
const map = function () {
var payload = this.payload;
if (payload) {
payload = payload.toLowerCase().split(" ");
for (var i = payload.length - 1; i >= 0; i--) {
payload[i] = payload[i].replace(/[^\w\s]|_/g, "").replace(/\s+/g, " ");
if (payload[i] && payload[i].length > 7) {
emit(payload[i], 1); // store a 1 for each word
}
}
}
}
const reduce = function(key, values) {
var count = 0;
values.forEach(function (v) {
count += v;
});
return count;
}
router.get('/counts', function (req, res) {
const filters = paramsParser.parse(req.query);
mongo.mapReduce(map, reduce, filters)
.then(function (data) {
const topics = data
.sort((a, b) => b.value - a.value)
.slice(0, 10)
.map(function(topic) {
return { id: faker.random.uuid(), title: topic._id, score: topic.value }
});
res.json(topics);
})
.catch(function(err) {
log.error(err);
res.sendStatus(500);
});
});
};
module.exports = datapoints;
function mapReduce(map, reduce, filters) {
filters = filters ? filters : defaults;
return new Promise(function(resolve, reject) {
client.connect(uri(), function(err, db) {
db.collection(collection)
.mapReduce(map, reduce, { out: { inline: 1 }, query: filters.find, limit: filters.pageSize }, function(err, docs) {
if (err) {
reject(err);
}
resolve(docs);
});
});
});
}
回答1:
You are using Swisscom's Docker based MongoDB service.
Swisscom started mongod with security.javascriptEnabled
Enables or disables the server-side JavaScript execution. When disabled, you cannot use operations that perform server-side execution of JavaScript code, such as the $where query operator, mapReduce command and the db.collection.mapReduce() method, group command and the db.collection.group() method.
Swisscom enabled that flag because of security. It's a best practise for hardening MongoDB. Swisscom is open for technical arguments and discussions about that. Maybe Swisscom misses an important fact?
security:
authorization: enabled
javascriptEnabled: false
Swisscom offers an other MongoDB service (not in docker container, 3 dedicated VMs with replication). There you don't have this limitation.
$ cf m -s mongodbent
Getting service plan information for service mongodbent as admin...
OK
service plan description free or paid
small3rs Replica Set with 3 data bearing nodes with 32 GB memory, 320 GB storage, unlimited concurrent connections paid
medium3rs Replica Set with 3 data bearing nodes with 48 GB memory, 480 GB storage, unlimited concurrent connections paid
large3rs Replica Set with 3 data bearing nodes with 64 GB memory, 640 GB storage, unlimited concurrent connections paid
With this plan you will receive Enterprise version of MongoDB and access to Ops Manager. In Ops Manager you will see nice HTML5 graphs with MongoDB metrics. It's nice GUI frontend for db.runCommand( { serverStatus: 1 } ) with history.
来源:https://stackoverflow.com/questions/40179448/mongodb-cannot-run-map-reduce-without-the-js-engine