Using regex to Retrieve multiple data from Mongodb - node.js

I am new to Mongodb
Here is what i have tried. however this method worked for me but its way slow.
Is it possible to design single query to get all this data. instead of querying one by one.
var Schema = mongoose.Schema;// Schema
var dataModelSchema = new Schema({
data: String,
});
var fdevices = mongoose.model('fdevices', dataModelSchema);
var DPMPow = fdevices.findOne({ "Data": { $regex: /DPMPow_P01/i } }).sort({
field: 'asc', _id: -1 }); //Active Power
var DPMAmp = fdevices.findOne({ "Data": { $regex: /DPMAmp_P01/i } }).sort({
field: 'asc', _id: -1 });//Total Current
var DPMkWh = fdevices.findOne({ "Data": { $regex: /DPMkWh_P01/i } }).sort({
field: 'asc', _id: -1 });//Consumption
var MxPeak = fdevices.findOne({ "Data": { $regex: /MxPeak_P01/i } }).sort({
field: 'asc', _id: -1 });//Max Demand Peak
var MPPeak = fdevices.findOne({ "Data": { $regex: /MPPeak_P01/i } }).sort({
field: 'asc', _id: -1 });//Max Demand Partial
async.series([
function (callback) {
DPMPow.exec(function (err, res) {
callback(null, res);
})
},
function (callback) {
DPMAmp.exec(function (err, res) {
callback(null, res);
});
},
function (callback) {
DPMkWh.exec(function (err, res) {
callback(null, res);
})
},
function (callback) {
MxPeak.exec(function (err, res) {
callback(null, res);
})
}, function (callback) {
MPPeak.exec(function (err, res) {
callback(null, res);
})
//chiller1
}
], function (err, results) {
console.log(results);
});
this is how my data looks like in database. in collection got only one field which name as 'Data' this field receives multiple sensors data in every one hour.
{ _id: 5b2118c4ae33249711a498a6,
Data: '13-06-2018 20:14:46 DPMPow_P01_04_ 699.15 ',
__v: 0 },
{ _id: 5b2118c4ae35439711a498a6,
Data: '13-06-2018 20:14:46 MPPeak_P01_04_ 699.15 ',
__v: 0 },
{ _id: 5b23428c4ae32989711a498a6,
Data: '13-06-2018 20:14:46 DPMAmp_P01_04_ 699.15 ',
__v: 0 },
{ _id: 5b21234c4ae32989711a498a6,
Data: '13-06-2018 20:14:46 DPMkWh_P01_04_ 699.15 ',
__v: 0 },
{ _id: 5b2118c4ae34989711a598a6,
Data: '13-06-2018 20:14:46 MxPeak_P01_04_ 699.15 ',
__v: 0 }

You can try below RegEx in find query
let data = fdevices.find({ "Data": { $regex: /(DPMPow)|(MPPeak)|(DPMAmp)|(DPMkWh)|
(MxPeak)/gm } }).sort({ field: 'asc', _id: -1 });

Related

Remove one field from mongoDB collection

I have a mongoDB collection which I use with a mongoose Schema :
const balanceSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId, ref: 'user'
},
incomes: { Number },
fees: { Number },
},
{ strict: false })
I use the strict mode to false, so I can push any 'key' I want with its value.
I would like to delete just one of the "incomes" category, but I can't specify the line because there is no 'defined key'.
Here is an exemple of the data inside :
{
"_id": {
"$oid": "60c763df3d260204865d2069"
},
"incomes": {
"income1": 1300,
"anyKeyNameIWant": 400
},
"fees": {
"charge1": 29,
"charge2": 29,
"chargetest": 29,
"charge7": 29
},
"__v": 0,
}
I tried this, but no success :
module.exports.deleteOneBalance = (req, res) => {
let data = req.body
if (!ObjectID.isValid(req.params.id))
return res.status(400).send('ID unknown : ' + req.params.id);
BalanceModel.update(
{ _id: req.params.id },
{
$unset: { "incomes.salairetest": "400" }
}), (err, docs) => {
if (!err) res.send('Deleted. ' + data)
else console.log('Error : ' + err)
}
}
Any idea ?
There are several ways to delete fields with dynamic field names.
One solution is this one:
var unset = {};
unset["incomes." + "anyKeyNameIWant"] = null;
db.balanceModel.updateOne({ _id: req.params.id }, { $unset: unset })
Or you can use an aggregation pipelinie like this:
db.balanceModel.updateOne(
{ _id: req.params.id },
[
{ $set: { incomes: { $objectToArray: "$incomes" } } },
{ $set: { incomes: { $filter: { input: "$incomes", cond: { $ne: ["$$this.k", "anyKeyNameIWant"] } } } } },
{ $set: { incomes: { $arrayToObject: "$incomes" } } }
]
)
If you want to remove/unset specific value/(s) from the documents then you have to provide the complete path of that key.
Let's take an example if you want to remove anyKeyNameIWant then your path will be incomes.anyKeyNameIWant and the update query will be like this
db.sample.update(
{
_id: ObjectId("60c763df3d260204865d2069")},
{
$unset: {"incomes.anyKeyNameIWant":""}
})
In your code, you are passing an object having the key incomes in $unset which will remove the complete incomes key from the document
Here is the link to the official document in case you want more details $unset

How to improve the query performance it taking 30 sec to execute the query MongoDb

I am using node is along with mongoose.while I am executing this query its taking 30+ sec for execution
I think its due to looping how to improve the performance can anyone guide me I am new to mongoose
companies
.findById(
{
_id: companyProfile,
},
function(err, company) {
if (err) {
return res.status(400).send({
message: "Some Error Occured!",
});
} else {
var responseJson = [];
company.ambulances.forEach(function(doc) {
Gps.find({
$and: [
{
device: doc.deviceId,
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
],
})
.sort({
$natural: -1,
})
.limit(1)
.exec(function(err, gpsLocations) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
} else {
responseJson.push({
gps: gpsLocations,
});
if (
company.ambulances.length === responseJson.length
) {
res.json(responseJson);
}
}
});
});
}
},
)
.populate("ambulances");
Well, first try to convert the callbacks to Promises, in order the code to be easier to understand. Now about the speed, you can match all the Gps objects using the $in operator. So the result will be something like that.
try {
const company = await companies.findById({ _id: companyProfile });
const gpsLocations = await Gps.find({
$and: [
{
device: { $in: company.ambulances },
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
]
}).sort({
$natural: -1,
}).populate("ambulances");
return res.json(gpsLocations.map(gpsLocation => ({
gps: gpsLocation,
})));
} catch(e) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
}

find multiple document ascending with limit 1 mongoose

I am new to Mongodb.
This is what i have tried
var fdevices = mongoose.model('fdevices', dataModelSchema);
var DPMPow = fdevices.findOne({ "Data": { $regex: /DPMPow_P01/i }
}).sort({ field: 'asc', _id: -1 });
var DPMAmp = fdevices.findOne({ "Data": { $regex: /DPMAmp_P01/i }
}).sort({ field: 'asc', _id: -1 });
var DPMkWh = fdevices.findOne({ "Data": { $regex: /DPMkWh_P01/i }
}).sort({ field: 'asc', _id: -1 });
var MxPeak = fdevices.findOne({ "Data": { $regex: /MxPeak_P01/i }
}).sort({ field: 'asc', _id: -1 });
var MPPeak = fdevices.findOne({ "Data": { $regex: /MPPeak_P01/i }
}).sort({ field: 'asc', _id: -1 });
function getReady() {
async.series([
function (callback) {
DPMPow.exec(function (err, res) {
callback(null, res);
})
},
function (callback) {
DPMAmp.exec(function (err, res) {
callback(null, res);
});
},
function (callback) {
DPMkWh.exec(function (err, res) {
callback(null, res);
})
},
function (callback) {
MxPeak.exec(function (err, res) {
callback(null, res);
})
}, function (callback) {
MPPeak.exec(function (err, res) {
callback(null, res);
}) ], function (error, results) {
console.log(results);
}
);
}
above method works for me but its very slow. is there a way i can design single query and get same result instead of queering data one by one.
In my collection i have single field called "Data" and my collection contains more than a one million document.
var fdevices = mongoose.model('fdevices', dataModelSchema);
var DPMPow = fdevices.find({
$or: [{
"Data": { $regex: /DPMPow/i }
}, {
"Data": { $regex: /DPMAmp/i }
}, {
"Data": { $regex: /DPMkWh/i }
}, {
"Data": { $regex: /MxPeak/i }
}, {
"Data": { $regex: /MPPeak/i }
}]
}).sort({ field: 'asc', _id: -1 });
DPMPow.exec(function(err, res) {
//Now travese thru all the records, when ever you find the unique pattren of
//data remove all the instances of that particular pattren
});

Mongoose: Push or replace element into array

I'm using Mongoose (MongoDB in node.js), and after reading this answer:
Replace value in array
I have another question:
Is it possible to do in the same sentence: push element into array or replace if this element is existing in the array?
Maybe something like this? (The example doesn't work)
Model.findByIdAndUpdate(id,
{
$pull: {"readers": {user: req.user.id}},
$push:{"readers":{user: req.user.id, someData: data}}
},{multi:true},callback)
Message error:
errmsg: 'exception: Cannot update \'readers\' and \'readers\' at the same time
Reference:
https://stackoverflow.com/a/15975515/4467741
Thank you!
Multiple operations on the same property path are simply not allowed in a single request, with the main reason being that the operations themselves have "no particular order" in the way the engine assigns them as the document is updated, and therefore there is a conflict that should be reported as an error.
So the basic abstraction on this is that you have "two" update operations to perform, being one to "replace" the element where it exists, and the other to "push" the new element where it does not exist.
The best way to implement this is using "Bulk" operations, which whilst still "technically" is "two" update operations, it is however just a "single" request and response, no matter which condition was met:
var bulk = Model.collection.initializeOrderedBulkOp();
bulk.find({ "_id": id, "readers.user": req.user.id }).updateOne({
"$set": { "readers.$.someData": data } }
});
bulk.find({ "_id": id, "readers.user": { "$ne": req.user.id } }).updateOne({
"$push": { "readers": { "user": req.user.id, "someData": data } }
});
bulk.execute(function(err,result) {
// deal with result here
});
If you really "need" the updated object in result, then this truly becomes a "possible" multiple request following the logic where the array element was not found:
Model.findOneAndUpdate(
{ "_id": id, "readers.user": req.user.id },
{ "$set": { "readers.$.someData": data } },
{ "new": true },
function(err,doc) {
if (err) // handle error;
if (!doc) {
Model.findOneAndUpdate(
{ "_id": id, "readers.user": { "$ne": req.user.id } },
{ "$push": { "readers":{ "user": req.user.id, "someData": data } } },
{ "new": true },
function(err,doc) {
// or return here when the first did not match
}
);
} else {
// was updated on first try, respond
}
}
);
And again using you preferred method of not nesting callbacks with either something like async or nested promise results of some description, to avoid the basic indent creep that is inherrent to one action being dependant on the result of another.
Basically probably a lot more efficient to perform the updates in "Bulk" and then "fetch" the data afterwards if you really need it.
Complete Listing
var async = require('async'),
mongoose = require('mongoose')
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var userSchema = new Schema({
name: String
});
var dataSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: 'User' },
someData: String
},{ "_id": false });
var testSchema = new Schema({
name: String,
readers: [dataSchema]
});
var User = mongoose.model( 'User', userSchema ),
Test = mongoose.model( 'Test', testSchema );
var userId = null,
id = null;
async.series(
[
// Clean models
function(callback) {
async.each([User,Test],function(model,callback) {
model.remove({},callback);
},callback);
},
// Create a user
function(callback) {
User.create({ name: 'bill' },function(err,user) {
userId = user._id;
callback(err);
});
},
function(callback) {
Test.create({ name: 'Topic' },function(err,topic) {
id = topic._id;
console.log("initial state:");
console.log(topic);
callback(err);
});
},
// 1st insert array 2nd update match 1 modified
function(callback) {
var bulk = Test.collection.initializeOrderedBulkOp();
bulk.find({ "_id": id, "readers.user": userId }).updateOne({
"$set": { "readers.$.someData": 1 }
});
bulk.find({ "_id": id, "readers.user": { "$ne": userId }}).updateOne({
"$push": { "readers": { "user": userId, "someData": 1 } }
});
bulk.execute(function(err,result) {
if (err) callback(err);
console.log("update 1:");
console.log(JSON.stringify( result, undefined, 2));
Test.findById(id,function(err,doc) {
console.log(doc);
callback(err);
});
});
},
// 2nd replace array 1st update match 1 modified
function(callback) {
var bulk = Test.collection.initializeOrderedBulkOp();
bulk.find({ "_id": id, "readers.user": userId }).updateOne({
"$set": { "readers.$.someData": 2 }
});
bulk.find({ "_id": id, "readers.user": { "$ne": userId }}).updateOne({
"$push": { "readers": { "user": userId, "someData": 2 } }
});
bulk.execute(function(err,result) {
if (err) callback(err);
console.log("update 2:");
console.log(JSON.stringify( result, undefined, 2));
Test.findById(id,function(err,doc) {
console.log(doc);
callback(err);
});
});
},
// clear array
function(callback) {
Test.findByIdAndUpdate(id,
{ "$pull": { "readers": {} } },
{ "new": true },
function(err,doc) {
console.log('cleared:');
console.log(doc);
callback(err);
}
);
},
// cascade 1 inner condition called on no array match
function(callback) {
console.log('update 3:');
Test.findOneAndUpdate(
{ "_id": id, "readers.user": userId },
{ "$set": { "readers.$.someData": 1 } },
{ "new": true },
function(err,doc) {
if (err) callback(err);
if (!doc) {
console.log('went inner');
Test.findOneAndUpdate(
{ "_id": id, "readers.user": { "$ne": userId } },
{ "$push": { "readers": { "user": userId, "someData": 1 } } },
{ "new": true },
function(err,doc) {
console.log(doc)
callback(err);
}
);
} else {
console.log(doc);
callback(err);
}
}
);
},
// cascade 2 outer condition met on array match
function(callback) {
console.log('update 3:');
Test.findOneAndUpdate(
{ "_id": id, "readers.user": userId },
{ "$set": { "readers.$.someData": 2 } },
{ "new": true },
function(err,doc) {
if (err) callback(err);
if (!doc) {
console.log('went inner');
Test.findOneAndUpdate(
{ "_id": id, "readers.user": { "$ne": userId } },
{ "$push": { "readers": { "user": userId, "someData": 2 } } },
{ "new": true },
function(err,doc) {
console.log(doc)
callback(err);
}
);
} else {
console.log(doc);
callback(err);
}
}
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Output:
initial state:
{ __v: 0,
name: 'Topic',
_id: 55f60adc1beeff6b0a175e98,
readers: [] }
update 1:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"insertedIds": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 1,
"nModified": 1,
"nRemoved": 0,
"upserted": []
}
{ _id: 55f60adc1beeff6b0a175e98,
name: 'Topic',
__v: 0,
readers: [ { user: 55f60adc1beeff6b0a175e97, someData: '1' } ] }
update 2:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"insertedIds": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 1,
"nModified": 1,
"nRemoved": 0,
"upserted": []
}
{ _id: 55f60adc1beeff6b0a175e98,
name: 'Topic',
__v: 0,
readers: [ { user: 55f60adc1beeff6b0a175e97, someData: '2' } ] }
cleared:
{ _id: 55f60adc1beeff6b0a175e98,
name: 'Topic',
__v: 0,
readers: [] }
update 3:
went inner
{ _id: 55f60adc1beeff6b0a175e98,
name: 'Topic',
__v: 0,
readers: [ { someData: '1', user: 55f60adc1beeff6b0a175e97 } ] }
update 3:
{ _id: 55f60adc1beeff6b0a175e98,
name: 'Topic',
__v: 0,
readers: [ { someData: '2', user: 55f60adc1beeff6b0a175e97 } ] }

Node JS Mongoose PULL query

I find many great answers here on SO like this answer an this. But i can not get it to work...
I tried ObjectId("55cf816559d2fc8d0e6c14a8") in the query where the id is.
This query works when robotmongo run it:
db.getCollection('events').update(
{ "_id": ObjectId("55cf816559d2fc8d0e6c14a8") },
{ "$pull": { "workers" : { "_id": ObjectId("55cf89ac7cba1d0a10ca86c7")}}},
false,
true
)
Side note, what is the false,true for?
Here is my current code
event.update(
{'_id': "55cf816559d2fc8d0e6c14a8"},
{ "$pull": { "workers" : {_id: "55cf89ac7cba1d0a10ca86c7"}}},
function(err, result) {
console.log(err);
console.log(result);
}
);
I do not get any errors and the result is equal to 1.
Works for me. You must be doing something differently and incorrectly:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var workerSchema = new Schema({
name: String
});
var eventSchema = new Schema({
name: String,
workers: [workerSchema]
});
var Event = mongoose.model( 'Event', eventSchema );
async.series(
[
function(callback) {
Event.remove({},function(err) {
callback(err);
});
},
function(callback) {
var event = new Event({
_id: "55cf816559d2fc8d0e6c14a8",
name: "Great thing"
});
event.workers.push({
_id: "55cf89ac7cba1d0a10ca86c7",
name: "Worker1"
});
event.save(function(err,event) {
console.log(event);
callback(err);
});
},
function(callback) {
Event.findOneAndUpdate(
{ "_id": "55cf816559d2fc8d0e6c14a8" },
{ "$pull": { "workers": { "_id": "55cf89ac7cba1d0a10ca86c7" } } },
{ "new": true },
function(err,event) {
console.log(event)
callback(err);
}
);
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
With the expected output:
{ __v: 0,
_id: 55cf816559d2fc8d0e6c14a8,
name: 'Great thing',
workers: [ { _id: 55cf89ac7cba1d0a10ca86c7, name: 'Worker1' } ] }
{ _id: 55cf816559d2fc8d0e6c14a8,
name: 'Great thing',
__v: 0,
workers: [] }

Resources