Creating Mongo/mapReduce data source in icCube - mongodb

I would like to create a MongoDB/mapReduce data source into icCube (http://www.iccube.com/support/documentation/user_guide/schemas_cubes/ds_mongodb.php#mapReduce), The below script works fine from Mongo shell, how it should be formatted to be accepted by icCube, when I paste the same code into icCube datasource builder, I get this error message:
MongoDB : invalid JSON (table:Test.mapReduce) : [var location_map = function() { if (this.companyId = "1234" && this.Parent_Location !== undefined && this.Parent_Location.value.length > 0 && this.Parent_Location.value[0].id !== undefined && this.Parent_Location.value[0].id !== null) { emit(this.Parent_Location.value[0].id, {Location_NameOfLocation: this.Location_NameOfLocation, LocationID: this._id, CountryName: "", companyId : 0}); } } var country_map = function() { if (this.companyId = "1234") { emit(this._id, { CountryName: this.CountryName, Location_NameOfLocation: "", LocationID: 0, companyId : this.companyId }); } } var r = function(key, values) { var result = {LocationID: 0, CountryName: "", Location_NameOfLocation: "", companyId : 0}; values.forEach(function(value) { if (result.LocationID === 0 && value.LocationID !== null ) { result.LocationID = value.LocationID; } if (result.companyId === 0 && value.companyId !== null ) { result.companyId = value.companyId; } if (result.CountryName === "" && value.CountryName !== null ) { result.CountryName = value.CountryName; } if (result.Location_NameOfLocation === "" && value.Location_NameOfLocation !== null ) { result.Location_NameOfLocation = value.Location_NameOfLocation; } }); return result; } db.runCommand( { mapReduce: Location, map: location_map, reduce: r, out: { replace: LocationsCountries }, query: {companyId : "1234"} } ) db.runCommand( { mapReduce: Countries, map: country_map, reduce: r, out: { reduce: LocationsCountries }, query: {companyId : "1234" } } )] ^
Mongo mapReduce script:
var location_map = function() {
if (this.companyId = "1234" && this.Parent_Location !== undefined && this.Parent_Location.value.length > 0 && this.Parent_Location.value[0].id !== undefined && this.Parent_Location.value[0].id !== null) {
emit(this.Parent_Location.value[0].id, {Location_NameOfLocation: this.Location_NameOfLocation, LocationID: this._id, CountryName: "", companyId : 0});
}
}
var country_map = function() {
if (this.companyId = "1234") {
emit(this._id, { CountryName: this.CountryName, Location_NameOfLocation: "", LocationID: 0, companyId : this.companyId });
}
}
var r = function(key, values) {
var result = {LocationID: 0, CountryName: "", Location_NameOfLocation: "", companyId : 0};
values.forEach(function(value) {
if (result.LocationID === 0 && value.LocationID !== null ) { result.LocationID = value.LocationID; }
if (result.companyId === 0 && value.companyId !== null ) { result.companyId = value.companyId; }
if (result.CountryName === "" && value.CountryName !== null ) { result.CountryName = value.CountryName; }
if (result.Location_NameOfLocation === "" && value.Location_NameOfLocation !== null ) { result.Location_NameOfLocation = value.Location_NameOfLocation; }
});
return result;
}
db.runCommand(
{
mapReduce: "Location",
map: location_map,
reduce: r,
out: { replace: "LocationsCountries" },
query: {companyId : "1234"}
}
)
db.runCommand(
{
mapReduce: "Countries",
map: country_map,
reduce: r,
out: { reduce: "LocationsCountries" },
query: {companyId : "1234" }
}
)
Thanks,
Balint

You'll have to define your functions in strings ( and Javascript escape if required strings within these strings ). This is described here in the icCube documentation ( www ). Here is an example combining single quoted strings with double-quoted strings.
{
"mapReduce": "Location",
"map": 'function() {
if (this.companyId = "1234" && this.Parent_Location !== undefined && this.Parent_Location.value.length > 0 && this.Parent_Location.value[0].id !== undefined && this.Parent_Location.value[0].id !== null) {
emit(this.Parent_Location.value[0].id, {Location_NameOfLocation: this.Location_NameOfLocation, LocationID: this._id, CountryName: "", companyId : 0});
}
}',
"reduce": 'function(key, values) {
var result = {LocationID: 0, CountryName: "", Location_NameOfLocation: "", companyId : 0};
values.forEach(function(value) {
if (result.LocationID === 0 && value.LocationID !== null ) { result.LocationID = value.LocationID; }
if (result.companyId === 0 && value.companyId !== null ) { result.companyId = value.companyId; }
if (result.CountryName === "" && value.CountryName !== null ) { result.CountryName = value.CountryName; }
if (result.Location_NameOfLocation === "" && value.Location_NameOfLocation !== null ) { result.Location_NameOfLocation = value.Location_NameOfLocation; }
});
return result;
}',
"out": {
"replace": "LocationsCountries"
},
"query": {
"companyId" : "1234"
}
}

Related

TypeError: pipeline[(pipeline.length - 1)] is undefined

I am running mongodb queries dynamically I am getting this error :
TypeError: pipeline[(pipeline.length - 1)] is undefined :
The following is my query :
var a = { "aggregate" : "income", "pipeline" : [ {$match:{sal : {$gt : 10000}}},{ "$skip" : 0}, { "$limit" : 5000 }], "cursor" : { "batchSize" : 5000 } };
if(a["aggregate"] != undefined)
{
var collectionName = a["aggregate"];
var query = a["pipeline"];
print(query)
for(var k = 0;k<query.length;k++)
{
var b = query[k]
if(b["$skip"] != undefined)
{
delete query[k];
}
if(b["$limit"] != undefined)
{
delete query[k];
}
}
print(query)
db.getCollection(collectionName).aggregate(query)
}
Please help
Regards
Kris
Hope this answer may help someone:
var a = { "aggregate" : "income", "pipeline" : [ {$match:{sal : {$gt : 10000}}},{ "$skip" : 0}, { "$limit" : 5000 }], "cursor" : { "batchSize" : 5000 } };
if(a["aggregate"] != undefined)
{
var collectionName = a["aggregate"];
var foo = [];
var query = a["pipeline"];
print(query)
for(var k = 0;k<query.length;k++)
{
var b = query[k]
if(b["$skip"] != undefined)
{
delete query[k];
}
else if(b["$limit"] != undefined)
{
delete query[k];
}
else
{
foo.push( query[k]);
}
}
db.getCollection(collectionName).aggregate(foo)
}

How can I pass a variable in sort funtcion of mongobd?

I want to pass this name variable in sort function. I am getting the value of name in console.log but its not working in sort function.
var coldata = req.body.order[0].column;
var name = req.body.columns[coldata].data; // Want to pass this variable in sort()
var first = req.body.order[0].dir;
var last = req.body.order[0].dir;
var x,y;
if (first == 'asc'){
x = 1
}else{
x = -1;
}
if (last == 'asc'){
y = 1
}else{
y = -1;
}
var searchStr = req.body.search.value;
if(req.body.search.value)
{
var regex = new RegExp(req.body.search.value, "i")
searchStr = { $or: [{'firstname':regex },{'lastname': regex}] };
}
else
{
searchStr={};
}
console.log(req.body.search.value)
var recordsTotal = 0;
var recordsFiltered=0;
console.log(searchStr);
db.count({}, function(err, c) {
recordsTotal=c;
db.count(searchStr, function(err, c) {
recordsFiltered=c;
db.find(searchStr, 'firstname lastname',{'skip': Number( req.body.start), 'limit': Number(req.body.length) }, function (err, results) {
if (err) {
console.log('error while getting results'+err);
return;
}
var data = JSON.stringify({
"draw": req.body.draw,
"recordsFiltered": recordsFiltered,
"recordsTotal": recordsTotal,
"data": results
});
res.send(data);
}).sort({name:x});// Not getting value of name here
});
});
});
You can use an aggregation pipeline
const sort = {};
sort[name] = x
const pipeline = [
{ $match: searchStr },
{ $skip: Number( req.body.start) },
{ $limit: Number( req.body.length) },
{ $sort: sort }
];
db.aggregate(pipeline) ...

failed to execute mongo like query

This is my mongo query and I'm passing it dynamically but its returning all data,
I'm passing in postman body parameters as keyup[processor] and value as 62, so I need that my query should return all data which has 62 in it, but I'm getting all data.
Please do guide me with this mongo query
if(req.body.keyup) {
for(var i in req.body.keyup) {
var keyValue = (req.body.keyup[i] === '.' || isNaN(req.body.keyup[i])) ? 999999 : req.body.keyup[i];
if(i === 'price') {
match['$and'].push({
[i] : +keyValue
});
} else if (!findQuery[i]) {
if (excludeOption.indexOf(i) !== -1) {
if (req.body.keyup[i] === 'blank') {
findQuery[i] = {
'$in' : [null]
};
} else {
findQuery[i] = +keyValue;
console.log('line 74',findQuery)
}
} else {
if (req.body.keyup[i] === 'blank') {
findQuery[i] = {
'$in' : [null, 'none', 'None', '', ' ', '-']
};
} else {
findQuery[i] = {
'$regex' : `\\${req.body.keyup[i]}`
};
console.log('##############')
}
}
I'm getting this on console
{ processor: { '$regex': '\\6' } }
when I run this raw query in mongo I'm getting the output correct

Sailsjs native with Mapreduce

I am working on sailsjs project, i just looking for suggestion to achieve the below output to make best performance with code samples.
My existing collection having this below document.
[{
"word" : "DAD",
"createdAt":"6/10/2016 7:25:59 AM",
"gamescore":1
},
{
"word" : "SAD",
"createdAt":"6/09/2016 7:25:59 AM",
"gamescore":1
},
{
"word" : "PAD",
"createdAt":"6/10/2016 8:25:59 AM",
"gamescore":1
}]
I need the below output which is something like this.
[{
"word" : "A",
"repeatedTimes" : "3",
"LatestRepeatedTime": "6/10/2016 8:25:59 AM"
},
{
"word" : "D",
"repeatedTimes" : "4",
"LatestRepeatedTime": "6/10/2016 8:25:59 AM"
},
{
"word" : "P",
"repeatedTimes" : "1",
"LatestRepeatedTime": "6/10/2016 8:25:59 AM"
},
{
"word" : "S",
"repeatedTimes" : "1",
"LatestRepeatedTime": "6/09/2016 8:25:59 AM"
}]
For the above scenario i implemented the below code to fetch, but it is not working at find query.
var m = function () {
var words = this.word;
if (words) {
for (var i = 0; i < words.length; i++) {
emit(words[i], 1);
}
}
}
var r = function (key, values) {
var count = 0;
values.forEach(function (v) {
count += v;
});
return count;
}
console.log(req.params.childid);
Activity.native(function (err, collection) {
console.log("hello");
collection.mapReduce(m, r, {
out: {merge: "words_count" + "_" + "575a4952bfb2ad01481e9060"}
}, function (err, result) {
Activity.getDB(function (err, db) {
var colname = "words_count" + "_" + "575a4952bfb2ad01481e9060";
var natCol = db.collection('words_count' + "_" + "575a4952bfb2ad01481e9060");
natCol.find({},..... **is not working**
natCol.count({}, function (err, docs) {
console.log(err);
console.log(docs);
res.ok(docs);
});
});
});
});
Answer:
natCol.aggregate([
{
$project:
{
_id: "$_id" ,
value:"$value"
}
}
], function(err, data){
console.log(data);
res.ok(data);
});
You could try the following
var m = function () {
if (this.word) {
for (var i = 0; i < this.word.length; i++) {
emit(this.word[i], {
"repeatedTimes": 1,
"LatestRepeatedTime": this.createdAt
});
}
}
};
var r = function (key, values) {
var obj = {};
values.forEach(function(value) {
printjson(value);
Object.keys(value).forEach(function(key) {
if (!obj.hasOwnProperty(key)) obj[key] = 0;
if (key === "repeatedTimes") obj[key] += value[key];
});
obj["LatestRepeatedTime"] = value["LatestRepeatedTime"];
});
return obj;
};
var opts = { out: {inline: 1} };
Activity.native(function (err, collection) {
collection.mapReduce(m, r, opts, function (err, result) {
console.log(err);
console.log(result);
res.ok(result);
});
});

jstree initially_select and initially_open

The below lines of code while using jstree, throws an exception mentioned in the link
http://code.google.com/p/jstree/issues/detail?id=294
**"ui" : { "initially_select" : [ quotedAndCommaSeparated ] }**
**"core" : { "animation" : 0, "initially_open" : [ quotedAndCommaSeparated ] }**
If i use hard coded values like below, it works without any issues.
"ui" : { "initially_select" : ['3381','7472','7473','7474','7247','7248','7249','3273','3272'] }
"core" : { "animation" : 0, "initially_open" : [ '3381','7472','7473','7474','7247','7248','7249','3273','3272' ] }
I have formed the quotedAndCommaSeparated from an array and it is the same as the hard coded values above. But still the issue is not resolved. Please suggest.
quotedAndCommaSeparated = '3381','7472','7473','7474','7247','7248','7249','3273','3272'
Complete code for ur reference:
For Scripts:
static.jstree.com/v.1.0pre/jquery.jstree.js
static.jstree.com/v.1.0pre/_docs/syntax/!script.js
function BindTreeView(nodeToHighlight, isInitialLoad)
{
var initiallySelect = [];
var searchOption = 0;
if($('#rbobtnSelectedLevelAndBelowRadio:checked').val() == 'Selected Level and Below')
searchOption = 1;
else if($('#rdobtnCurrentOrganization:checked').val() == 'Current Organization')
searchOption = 2;
if(searchOption == 0)
initiallySelect.push(nodeToHighlight);
else if (searchOption == 1 || searchOption == 2)
{
var grid = $("#SearchResultJQGrid");
ids = grid.jqGrid("getDataIDs");
if(ids && ids.length > 0)
{
for(var iRow = 1; iRow < ids.length; iRow++)
{
var dataRow = $("#SearchResultJQGrid").getRowData(iRow);
var companyId = dataRow.CompanyID;
initiallySelect.push(companyId);
}
}
}
var quotedAndCommaSeparated = "'" + initiallySelect.join("','") + "'";
var urlRef = '/Group/GetDataForTreeView';
$('#TreeView').jstree({
"json_data" : {
"ajax" : {
"cache": false,
"url": function (node) {
var nodeId = "";
if (node == -1)
url = urlRef;
return url;
},
"data" : function (n) {
return { id : n.attr ? n.attr("id") : 0 };
}
}
},
"ui" : { "initially_select" : [ quotedAndCommaSeparated ] },
"core" : { "animation" : 0, "initially_open" : [ quotedAndCommaSeparated ] },
"themes": {
"theme": "classic",
"dots": true,
"icons": false
},
"plugins" : [ "themes", "json_data", "ui", "core" ]
}).bind("select_node.jstree", function (event, data) { if(isInitialLoad == true)
isInitialLoad = false;
else
BindGridView('CV', data.rslt.obj.attr("name"), data.rslt.obj.attr("id"), isInitialLoad);
});
}
Your bug is that quotedAndCommaSeparated is not a list, it's just a string.
You should simply add strings instead of numbers to the initiallySelect list
initiallySelect.push(companyId + "");
Then you can use this directly in the jstree init
"ui" : { "initially_select" : [ initiallySelect ] },
Hope that helps.