How to create a mongoose object and simultaneously log the _id - javascript

I'm creating subdocuments in my event model under guests that look like below. I would like to console.log the corresponding subdoc Id as each guest id is created.
{
"guests" : [
{ "phone" : 11111,
"_id" : ObjectId("61ef629981f154bead6b0de4")
},
{ "phone" : 4444444444,
"_id" : ObjectId("61fca19f95b626e017732139")
}
]
}
I followed the mongoose docs but the code from the docs (below) only logs the first id even as each subsequent doc is created because of the index 0.
// create a comment
parent.children.push({ name: 'Liesl' });
const subdoc = parent.children[0];
console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
subdoc.isNew; // true
I tried removing the index 0 and the console log just produces the ever-growing guests array.
module.exports.addGuest = async (req, res) => {
const event = await Event.findById(req.params.id);
const phone = req.body.guest;
event.guests.push(phone);
const guestId = event.guests[0];
console.log(guestId);
await event.save();
res.redirect(`/events/${event._id}`);
}
How do I adjust my function to log the corresponding subdoc Id as it's created?

try applying mongoose hooks on your subschema.
mongoose pre save hook is triggered every time a document is saved in your collection and you can log the id of your document which is being saved.

Related

Compare if ObjecticID already exist or not in array

In mongo, I made history column array for each user to get the Id of specific card, so I would like to made a condition or not for knowing that :
To understand my code :
find the ID user, find his history :
if card ID already present => don't duplicate ID on this array
but, if is not present :
add the ID on his own history array.
My req.body._id is the Id value who the user submit
const forThisUser = { _id: req.user._id }
const condition = await User.find(forThisUser, {"history" : { $in : req.body._id}})
async function alreadyPresentOrNot(res, req){
if(condition>0){
console.log("Already present !")
res.sendStatus(401);
}
else{
console.log("Card not finding, add on array now !")
await User.findOneAndUpdate(forThisUser, { $addToSet: { history: req.body._id } }, {upsert: true})
res.sendStatus(201);
}
}
I got this error :
ERROR Expression $in takes exactly 2 arguments. 1 were passed in.
Thanks
Just try using it in an array.
const ids = [req.body._id];
const condition = await User.find(forThisUser, {"history" : { $in : [ids]}})
Here is the official link that says you have to use $in : [array]
https://mongoosejs.com/docs/api/aggregate.html?
Please refer to Monngoose's documentation:
Your query should be:
const forThisUser = { _id: req.user._id }
const condition = await User.find({...forThisUser, "history" : { $in : req.body._id}})
Find takes the filters argument as an object, which would be:
{
_id: req.user._id,
history: { $in: req.body._id }
}
Unrelated to your question, but you may want to have a look at your HTTP response codes as well.
For example, for a duplicated entry you would return a 409 Conflict, or a 400 Bad Request not a 401 Unauthorized.
And if the card is added you can return 200 Success or 204 No Conntent, unless you are creating the card resource in that same request your return 201 Created

Get the _id of the created element instead of the whole data in mongodb

I have a problem accessing the _id of the last created element inserted in to mongodbe.
is there any solution to just get the id, instead of getting all elements? especially if the data list is so long and nested so its really hard to pin the created element and gain access to his id
I am using mongoose driver on this one.
let updateDeptArr = await Budget.findOneAndUpdate(
// Dynamic
{
'_id': `${propertyValues[0]}`, // user ID
[`${keys[2]}._id`]: `${propertyValues[1]}`
},
{
'$push': {
[`${keys[2]}.$.${keys[3]}`]: propertyValues[3]
}
}, { _id: true, new: true }
).then(function (data) {
// we need to get and send The id of the last created element!!!
console.log(data[keys[2]]);
// let order = data[keys[1]].length - 1
// let id = data[keys[1]][`${order}`]._id
// res.json({ _id: id })
})
}
You can use select after query.
In the upcoming listing, you have a mongoose schema being used to query MongoDB, and just two fields are selected, as you want.
Loc
.findById(req.params.locationid)
.select('name reviews')//select chained
.exec();
Try to chain select to your call. It will just give back the name and reviews.
Try this:
let updateDeptArr = await Budget.findOneAndUpdate(
// Dynamic
{
'_id': `${propertyValues[0]}`, // user ID
[`${keys[2]}._id`]: `${propertyValues[1]}`
},
{
'$push': {
[`${keys[2]}.$.${keys[3]}`]: propertyValues[3]
}
}, { _id: true, new: true }
).select("_id")// not sure if Mongoose will chain this way
.then(function (data) {
// we need to get and send The id of the last created element!!!
console.log(data[keys[2]]);
// let order = data[keys[1]].length - 1
// let id = data[keys[1]][`${order}`]._id
// res.json({ _id: id })
})
}

I want to add data in mongo collection while updating, but instead its getting updated

I want to add data while I am updating, So the use cases is to add the data in same object when I am making a for loop to store the data into the database. But When I am trying to do this then its getting updated instead of adding in into current present object.
const update_records = async (_id, fileName, filter) => {
try {
await connect_to_mongo();
const result = await execute_reports_model.findOneAndUpdate(_id, {upsert: true}, function (err, doc){
if(err || doc === null){
console.error(err);
const e = new Error('ID not found.');
e.status = 404;
throw e;
}
doc.file_name = fileName;
doc.filters.id = filter._id
doc.filters.name = filter.name
doc.filters.origin = filter.origin
doc.save();
})
return result;
} catch (error) {
console.error(error);
throw error;
}
}
In above function i am trying to add data into existing data which is present in the mongo collection.(using mongoose)
{
"_id" : ObjectId("5f16f4e1291796bb531a06df"),
"student)_count" : 5,
"batch_key" : "ddddwe3-6e4a-4654-8f18-c44b152c52c3",
"report_id" : "5f0ffbcdd264d70c1a3b143aa",
"__v" : 0,
"file_name" : "Student Copy Demand file",
"filters" : {
"id" : "5f0ffb96d67d70c1a3b143e7",
"name" : "USER 2 cards filter",
"origin" : "USER"
}
}
Lets say this above is the data available in the collection.
Now i one for loop I am updating the data with id of the same data.
await update_records(_id, fileName, row);
here in above code, row is for loop row which contains filters, and filters needs to be added with filename in the existing record for which that I will find by that _id
example if row contains below data
{
"id" : "2f0f3fb496d670c513iuroinm",
"name" : "Student Daily attendence",
"origin" : "Student"
}
Then that updated record would look like this:
{
"_id" : ObjectId("5f16f4e1291796bb531a06df"),
"student)_count" : 5,
"batch_key" : "ddddwe3-6e4a-4654-8f18-c44b152c52c3",
"report_id" : "5f0ffbcdd264d70c1a3b143aa",
"__v" : 0,
"file_name" : "Student Copy Demand file",
"filters" : {
"id" : "5f0ffb96d67d70c1a3b143e7",
"name" : "USER 2 cards filter",
"origin" : "USER"
},
{
"id" : "2f0f3fb496d670c513iuroinm",
"name" : "Student Daily attendence",
"origin" : "Student"
}
}
Also this is how my model looks like
report_id:{type:String,trim:true},
file_name:{type:String},
filters:[{
status:{type:String}, // this would updated in another function
id:{type:String},
name:{type:String},
origin:{type:String}
}],
batch_key:{type:String,trim:true},
How can I achieve this?
Edited: Made Model filters Array
const result = await execute_reports_model.findByIdAndUpdate(
_id,
{
$set:
{
filters: [filters_data],
}
});
This above code is updating the filed not inserting another one.
All I want to add new, not update the existing.
I see that you are trying to add new filter object to the filters field, but filters field is the object so it's always replaced.
To add new filter in the filters, you must make filters array and then just append it.
Here first of all your model is depicting the wrong meaning. Your filters should be an array.
If you want more than one object to be stored with commas you should have the array data type for the filters.
Make other model for the object that you need to store in the array of filters.
Lets call it filterModel.
Then your main model should look like:
report_id:{type:String,trim:true},
file_name:{type:String},
filters: filterModel[]=[]
batch_key:{type:String,trim:true},
And your filterModel should have the following:
status:{type:String}, // this would updated in another function
id:{type:String},
name:{type:String},
origin:{type:String}
Edited:
Hello, instead of using set operation you should use push operation to add the entry in the array and not replace the existing values.
So please try the below line of codes.
const result = await execute_reports_model.findByIdAndUpdate(
_id,
{
$push:
{
filters: filters_data,
}
});

Get unique id of specific element in Firebase

I have my Firebase database structured like this:
{
"userProfile" : {
"X0u2SEFfYEeVmdw4TXl58ou2eYy1" : {
"email" : "jane#yahoo.com",
"name" : "Jane"
},
"cliv7hQ4FsWKTtYksPDXcdDafdi2" : {
"email" : "doe#gmail.com",
"name" : "John Doe",
}
}
}
I'm trying to get the unique id of the element that matches query criteria, for example the key of the element with email equal to doe#gmail.com.
I'm doing this by using:
firebase.database().ref('/userProfile').orderByChild('email').equalTo(email).once( 'value', data => {
let user = data.val();
});
This returns me the entire object with that email, but I only want its unique id ("cliv7hQ4FsWKTtYksPDXcdDafdi2" in this case). What's the best way to achieve this?
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So:
var query = firebase.database().ref('/userProfile').orderByChild('email').equalTo(email);
query.once( 'value', data => {
data.forEach(userSnapshot => {
let user = userSnapshot.val();
let key = userSnapshot.key;
});
});

Mongoose: Finding a user in a collection and checking if this user's array contains x?

I have a collection called 'users' where a typical user entry looks something like this:
{
"__v" : 0,
"_id" : ObjectId("536d1ac80bdc7e680f3436c0"),
"joinDate" : ISODate("2014-05-09T18:13:28.079Z"),
"lastActiveDate" : ISODate("2014-05-09T18:13:48.918Z"),
"lastSocketId" : null,
"password" : "Johndoe6",
"roles" : ['mod'], // I want this to be checked
"username" : "johndoe6"
}
I want to create an if function that finds a user variable targetuser, and checks to see if his 'roles' array contains a 'mod'.
How can this be done with mongoose?
It can be done easily. Code below describes in detail what must be done to achieve this.
Steps:
get mongoose module
connect to mongo and find the right database
make a schema of your collection (in this case only users)
add a custom method that returns true if the role 'mod' exists in the array. Note: mongo collection doesn't have structure, so it might be good to run a check if the property 'roles' exists and it is an array.
model the created schema.
test it by finding random (one) document/user and check if it is a moderator.
So, this is programmed as:
// get mongoose.
var mongoose = require('mongoose');
// connect to your local pc on database myDB.
mongoose.connect('mongodb://localhost:27017/myDB');
// your userschema.
var schema = new mongoose.Schema({
joinDate : {type:Date, default:Date.now},
lastActiveDate: Date,
lastSocketId : String,
username : String,
password : String,
roles : Array
});
// attach custom method.
schema.methods.isModerator = function() {
// if array roles has text 'mod' then it's true.
return (this.roles.indexOf('mod')>-1);
};
// model that schema giving the name 'users'.
var model = mongoose.model('users', schema);
// find any user.
model.findOne({}, function(err, user)
{
// if there are no errors and we found an user.
// log that result.
if (!err && user) console.log(user.isModerator());
});

Categories

Resources