use variable as key name in mongo db with modifier - node.js

I am trying to insert a bunch of arrays into mongoDB.
The data looks something like:
var places = {
city: ['london', 'york', 'liverpool'],
country: ['uk', 'france']
};
Each time I add an array, some of the entries could already be there, so I want to ensure there are no duplicates.
db.collection('places').ensureIndex({'city': 1}, {unique: true }, function(){ });
db.collection('places').ensureIndex({'country': 1}, {unique: true }, function(){ });
I then need to loop through the places object and add each item:
for(var key in places){
db.collection('places').update({_id: 1}, { $addToSet: { key: { $each places[key] } } }, function(err, docs){
if(err){
console.log(err);
}else{
console.log('success');
}
});
}
Here I need key to be the actual keys: 'city', 'country'. Rather than literally being 'key'. But I cant see how this can be achieved with with the modifiers in place.

You need to build up your $addToSet value programmatically:
for(var key in places){
var addToSet = {};
addToSet[key] = { $each: places[key] };
db.collection('places').update({_id: 1}, {$addToSet: addToSet}, function(err, docs){
if(err){
console.log(err);
}else{
console.log('success');
}
});
}
But you can do this more efficiently by combining both updates into one:
var addToSet = {};
for(var key in places){
addToSet[key] = { $each: places[key] };
}
db.collection('places').update({_id: 1}, {$addToSet: addToSet}, function(err, docs){
if(err){
console.log(err);
}else{
console.log('success');
}
});

Related

Node.js MongoDB Find with projection to exclude _id still returns it

Trying to follow the examples here to filter by using a projection to exclude _id. The _id still returns:
Code
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/db1";
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbase = db.db("db1"); //here
dbase.collection("customers").find(
{},
{
_id: 0
}
).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
Result still return as follows:
[ { _id: 5a2bb2d6ee48575cb54c4365,
name: 'John',
address: 'Highway 71' }, { _id: 5a2bb2d6ee48575cb54c436d,
name: 'Susan',
address: 'One way 98' }, .... { _id: 5a2bb2d6ee48575cb54c4371,
name: 'Chuck',
address: 'Main Road 989' }, { _id: 5a2bb2d6ee48575cb54c4372,
name: 'Viola',
address: 'Sideway 1633' } ]
Theoretically _id should not be part of what is returned. What is wrong here?
To limit the fields you have to use fields option( dont know about new updates):
dbase.collection("customers").find({}, {
fields: { _id: 0 }
}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
UPDATE:
For version > 3 you have to use projection option instead:
dbase.collection("customers").find({}, {
projection:{ _id: 0 }
}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
In version 3 of the MongoDB API, the fields option has been deprecated. You should now use the projection option instead.
For example:
dbase.collection('customers').find({}, {
projection: {
_id: 0
}
}).toArray(function (err, result) {
if (err) {
throw err
}
console.log(result)
db.close()
})
The full list of supported options can be found here: http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#find
Starting in version 3.4, there is now an option for adding .project() outside of find().
Using ES8 async,await.
Ex:
async function connectDB(url) {
try {
const db = await MongoClient.connect(url);
const dbase = db.db("db1"); //here
const results = await dbase.collection("customers").find().project({_id:0}).toArray();
console.log(result);
db.close();
}
catch(err) {
throw err;
}
}
Docs here and another example here.

Get a list of inner properties with mongoose

I have a mongoose schema having the structure of
const videoProjectsSchema = new Schema({
projectname:String,
projectmeta:String,
username:String,
createdat:{ type: Date, default: Date.now }
});
I need to retrieve a list of projectnames which belongs to a particular user. the array returned should only contain the names of the projects or else a list of projectname. This is my code(which returns all the projects objects)
videoProjects.find({ username: req.query.username }, function(err, proj) {
if (err) {
console.log(err);
}
res.json(proj);
});
You can use fields as second parameter to limit fields returned in object.
videoProjects.find({ username: req.query.username },{projectmeta:0,username:0,createdat:0,_id:0},
function(err, proj) {
if (err) {
console.log(err);
}else
res.json(proj);
});
OR
videoProjects.find({ username: req.query.username },{projectname:1,_id:0},
function(err, proj) {
if (err) {
console.log(err);
}else
res.json(proj);
});

How to delete Element In MongoDB property's array with MongooseJS?

I cannot remove an element inside of an array that is a property of a MongoDB Model.
Please remember this is a NodeJS module mongooseJS and not the real MongoDB so functionalities are not the same..
GOAL: Delete an object from the statusLiked array. | I have also confirmed that the value of status.id is correct.
Model:
Const userSchema = new mongoose.Schema({
myStatus: Array,
statusLiked: Array,
)};
Delete:
1. Deletes the status(works). 2. Delete the status from User.statusLiked(no work).
exports.deleteStatus = (req, res, next) => {
var CurrentPost = req.body.statusid; // sends in the status.id
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
// vvvv this vvv
User.update( {id: req.user.id}, { $pullAll: {_id: CurrentPost }, function(err) { console.log('error: '+err) } });
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
};
What happens: The specific status(object) is deleted from the database. But the status still remains in the User.statusLiked array.
What I want to happen: Status to be deleted from the User.statusLiked array and the status to be deleted from the database. Then, reload the page and display a notification.
I got it to work somehow. Working code:
exports.deleteStatus = (req, res, next) => {
var CurrUser = req.body.userid;
var CurrentPost = req.body.post;
Status.remove({ _id: CurrentPost }, (err) => {
if (err) { return next(err); }
console.log('meeee'+CurrentPost+'user: ' +CurrUser);
req.flash('success', { msg: 'Status deleted.' });
res.redirect('/');
});
User.update(
{ _id: new ObjectId(CurrUser)},
{ $pull: { myStatus : { _id : new ObjectId(CurrentPost) } } },
{ safe: true },
function (err, obj) {
console.log(err || obj);
});
};

Unable to update the database using findAndModify

I'm using Node.js with mongodb.
var mongo = require("mongodb").MongoClient;
var url = process.env.MLAB_URI;
mongo.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established');
var sequence = db.collection('sequence')
//Find and modify the sequence counter.
var obj = sequence.findAndModify({
query: {_id: 1},
update: { $inc: {seq: 1}},
new: true
});
console.log(obj);
sequence.find({_id:1}).toArray(function(err,res){
if(err)
console.log(err);
else
console.log(res)
});
db.close();
}
});
But the above code is not updating the database and the output of obj that is returned is Promise { <pending> } .
The complete output is
Connection established
Promise { <pending> }
[ { _id: 1, seq: 0 } ]
I need to update the value and retrieve the object . Is there any way to do that?
Thanks in advance!
Please change the findAndModify as mentioned below.
var obj = sequence.findAndModify(
{_id: 1},
{},
{ $inc: {"seq": 1}},
{new:true, upsert:true}
);
Second option to avoid promise:-
Comment the console.log(obj);
var obj = sequence.findAndModify(
{_id: "1"},
{},
{ $inc: {"seq": 1}},
{new:true, upsert:true}, function (err, doc) {
if(err)
console.log(err);
else
console.log(doc);
}
);
You are referring the Mongo shell version and try implementing the same using NodeJS version. The NodeJS findAndModify version is little different.
In order to get the old value of seq, you can set the new flag to false and doc.value.seq gives you the old value (i.e. value before update).
sequence.findAndModify(
{_id: "1"},
{},
{ $inc: {"seq": 1}},
{new:false, upsert:true}, function (err, doc) {
if(err)
console.log(err);
else {
console.log(doc);
console.log(doc.value.seq);
}
});
change to
var obj = sequence.findOneAndModify({
_id: 1,
update: { $inc: {seq: 1}},
upsert: true
});

How to use findOneAndUpdate in MongoDB in Node

Say previously I had inserted a document into a mongo collection.
MongoClient.connect(url, function(err,db){
if(err) {throw err;}
else {
document = {action: "alert",
protocol: "udp",
port: "80",
_id: "12" }
var collection = db.collection("connections");
collection.insertOne(document, function(err,result){
if (err) {throw err;}
else {
console.log("Successful")
db.close();
}
}
}
Now I want to update the protocol field. What I have with no luck so far is
MongoClient.connect(url, function(err,db){
if (err) { throw err; }
else {
var collection = db.collection("connections");
collection.findOneAndUpdate({_id: "12"}, {$set: {protocol: "http"}}, {new: true}, function(err,doc) {
if (err) { throw err; }
else { console.log("Updated"); }
});
}
});
Am I passing the wrong parameters to the findOneAndUpdate method? I connect to the database correctly.
I think you should try
MongoClient.connect(url, function(err,db){
if (err) { throw err; }
else {
var collection = db.collection("connections");
collection.findOneAndUpdate({_id: "12"}, {$set: {protocol: "http"}}, {upsert: true}, function(err,doc) {
if (err) { throw err; }
else { console.log("Updated"); }
});
}
});
If "upsert" set to true, creates a new document when no document matches the query criteria.
=== Aug 2021
Here is an example of using findOneAndUpdate and getting back the updated document:
With the release of v4 of the node.js client, it seems the old solution of returnOriginal: false (which was awful anyway) is no longer the correct answer.
To see the list of available options for the node.js findOneAndUpdate method: https://mongodb.github.io/node-mongodb-native/4.0/interfaces/findoneandupdateoptions.html
But in short, this should work:
const doc = await <Collection>.findOneAndUpdate(
{ ... search },
{
$set: {
field1: 'value 1',
field2: ['value 2'],
etc.
},
},
{
upsert: true,
returnDocument: 'after', // this is new !
}
)
your third {new: true} argument is not valid
MongoClient.connect(url, function(err,db){
if (err) { throw err; }
else {
var collection = db.collection("connections");
collection.findOneAndUpdate({"_id": "12"}, {$set: {"protocol": "http"}}, function(err,doc) {
if (err) { throw err; }
else { console.log("Updated"); }
});
}
});
Here to update the record,it is not needed to use {upsert: true} and {new: true}. This solution works better.Try it once and suggest me if any errors in the code.
insert the update document if nothing matches the filter then use upsert.
MongoClient.connect(url, function(err,db){
if (err) { throw err; }
else {
var collection = db.collection("connections");
collection.findOneAndUpdate({_id: "12"}, {protocol: "http"}, {new: true}, function(err,doc) {
if (err) { throw err; }
else { console.log("Updated"); }
});
}
});

Resources