failed to execute mongo like query - mongodb

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

Related

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) ...

$in returning nothing when array is empty

This is my backend code for filters :
db.collection("users")
.find({
$or: [
{ job: { $in: myFilters.jobs } },
{ role: myFilters.role }
]
})
it works really well, when
myFilters.jobs = ["manager","user"]
The problem is when myFilters.jobs is an empty array [""], it should return all documents.
Currently, this is returning nothing, while I need it to return all docs :
myFilters.jobs = [""]
How could I do that, please ?
I've tried out this with no luck :
db.collection("users")
.find({
$or: [
$cond: {
if: { $ne: [myFilters.jobs, ""] },
then: { job: myFilters.jobs },
else: { job: { $in: myFilters.jobs } }
},
{ role: myFilters.role }
]
})
So, I'm trying to explain the solution I've found :
1st . In a node ws, I'm receiving filters, and cleaning them with this function :
This function removes emptys objects or arrays(It is when a user doesn't pick any filter inside of the app).
This is the JSON filters I'm receiving , please notice that, for example, role is empty, because the user has not chosen any role filter.
{"filters":{"role":"","jobs":["database"]}}
It goes through this function, so role gets deleted :
clean(myFilters);
function clean(obj) {
for (var propName in obj) {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === "" ||
!obj[propName].length
) {
delete obj[propName];
}
}
}
2nd ,
Then, I'm pushing the filters dynamically like this :
var find = {};
find.$and = [];
if (myFilters.role) {
find.$and.push({ role: myFilters.role });
}
if (myFilters.jobs) {
find.$and.push({ job: { $in: myFilters.jobs } });
}
Finally , this is the db.collection call :
db.collection("users")
.find(find)
.toArray(function(err, docs) {
res.send(docs);
});
SO , when a user doesn't pick a filter, the clean function is removing emptys selections ... Maybe there are better solutions ?
You can adjust your condition according to the values you get like this:
Using $where:
db.collection("users")
.find({ $where: function() {
return myFilters.jobs.includes(this.job) || this.role === myFilters.role
}})
JS only:
const cond = {};
if(myFilters.jobs.length === 0) {
cond.role = myFilters.role;
} else {
cond.$or = [
{ job: { $in: myFilters.jobs } },
{ role: myFilters.role }
];
}
db.collection("users")
.find(cond)
Update according to the OP's answer:
db.collection("users")
.find({ $where: function() {
let filter = true;
if(myFilters.jobs && myFilters.jobs.length) filter = myFilters.jobs.includes(this.members);
if(myFilters.role) filter = filter && this.name === myFilters.role;
return filter;
}})

MongoDB putting they key into $set instead of using it for lookup?

I am trying to update a message using userID as my _id
Is splitting it up into findOne - Save - Update the best way?
//
// Find and update message
//
var messageModel = require('../models/messageModel');
var messageTable = mongoose.model('messageModel');
var messageRecord = new messageModel();
var findMessage = () => {
return new Promise((resolve, reject) => {
console.log("=====START findMessage=====")
messageTable.findOne(
{ _id: userID }
,function(err, data) {
if (err) {
reject(new Error('findMessage: ' + err))
return;
}
// Who will have this as unread?
if (userManager==true) {
messageRecord.readUser = false;
messageRecord.readManager = true;
} else {
messageRecord.readUser = true;
messageRecord.readManager = false;
}
// If message not found, then create new one
if (!data) {
console.log("=====CREATE NEW RECORD=====")
messageRecord._id = userID;
messageRecord.activityDate = Math.round(new Date().getTime()/1000);
messageRecord.messages = {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
messageRecord.save(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})
console.log("=====RESOLVE findMessage=====")
resolve();
return;
}
// If message found, then add message
console.log("=====ADD LINE TO RECORD=====")
messageTable.update (
{ _id: userID },
{
$set: {
activityDate : Math.round(new Date().getTime()/1000),
readUser : messageRecord.readUser,
readManager : messageRecord.readManager
},
$push: {
messages: {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
}
},
{ upsert: true }
).exec(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})
console.log("=====RESOLVE findMessage=====")
resolve();
return;
});
})};
Do I need to put upsert:true? (what ever that means)
Or should I use findOneAndUpdate?
And would you use findOneAndUpdate or just update? And why?
I tought it went like this:
findone
if not found then save
if found then update
UPDATE - Thanks to lascot I ended up doing this, and it works great!
// Save message
messageTable.update (
{ _id: userID },
{
$setOnInsert: {
_id: userID
},
$set: {
activityDate : Math.round(new Date().getTime()/1000),
readUser : messageRecord.readUser,
readManager : messageRecord.readManager
},
$push: {
messages: {
"message" : message,
"date" : Math.round(new Date().getTime()/1000),
"property" : propertyID,
"booking" : bookingID,
"manager" : userManager
}
}
},
{ upsert: true }
).exec(function (err, res) {
if (err) {
reject(new Error('findMessage: ' + err));
return;
}
})

Sequelize - Cannot save associations in 1:N relationship

What you are doing?
trying to add associations and save them to database
js
var Device = models.Device;
var Log = models.Log;;
var logs = [
{
"message_level" : 1,
"message" : "test log 1"
},
{
"message_level" : 1,
"message" : "test log 2"
},
{
"message_level" : 1,
"message" : "test log 3"
}
];
var devID = 'X3dE4DEW';
describe('Logs', function() {
it('should create log', function(done) {
Device.create({
"originalID" : devID
}).then(
function() {
return Device.findOne({"where": {originalID: devID},
include: [ { model: Log, as : "Logs" } ] }).then(
function(device) {
if (device) {
logs = logs.map(
function(log) {
return Log.build(log);
}
);
console.log(logs) // is NOT Empty -> OK
return device.addLogs(logs).then(
function(device) {
return device.getLogs().then(
function(logs) {
console.log(logs); // EMPTY [] -> NOT OK
logs.length.should.equal(3);
done();
}
);
}
);
}
return Promise.reject('Not valid Device ID');
}
).catch(function(error){
console.log(error);
done();
});
}
);
});
});
here is how are they defined
// models
// Device
Device = pg.define('device', {
originalID: {
type: Sequelize.STRING(16) // Up to 16
}
});
// LogRecord
Log = pg.define('log', {
message_level: {
type: Sequelize.INTEGER
},
message: {
type: Sequelize.STRING(100) // Up to 100
}
});
Device.hasMany(Log, { as : "Logs" });
Log.belongsTo(Device);
What do you expect to happen?
addLogs should save associations items to the database
What is actually happening?
Items are not saved, device.getLogs() is returning an empty array []
{ AssertionError: expected 0 to equal 3 }
Dialect: PG
Database version: 9.6.1
Sequelize version: ~3.30.x
There's several solutions to associate rows
if you're using add<Association(s)> function, be sure that associated objects are already stored in database.
or you can use create<Association> to create model and associate.
var device;
Device.create({
"originalID" : devID
}).then(function(createdDevice) {
device = createdDevice;
return Promise.all(logs.map(log=>{return device.createLog(log);}));
}).then(function(result) {
return device.getLogs();
}).then(function(logs) {
console.log(logs);
logs.length.should.equal(3);
done();
}).catch(function(error){
console.log(error);
done();
});
Use promises style like above, it's more understandable, not "go deep into promises".

Creating Mongo/mapReduce data source in icCube

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"
}
}