Mongoose: Push data to array in for loop - node.js

i have small problem i have this code:
Messages.findOne({id_user: to}, function (err, toUser) {
//dopisujemy wiadomość w tablicy użytkownika
var messArray = toUser.messagesArray;
//przeszukujemy tablice z wiadomościami aby znaleźć odpowiedniego użytkownika
for(var i=0;i<messArray.length; ++i) {
if(messArray[i].id_converser = who) {
// console.log(messArray[i]);
toUser.messagesArray[i].messages.push({id_converser: who,message: message,date: Date()});
toUser.save(function (err) {
if(err) console.log(err);
console.log('Wiadomość dodana');
})
return;
}
}
}) //end zapisujemy wiadomość w miejscu przeznaczenia
and everything seems fine, in console i have message "wiadomosc dodana", but when i check it in database i not see this added data, why.
Thanks for reply.

In order to push to the array in the actual database you need to use $push or something like $addToSet operator

When you modify any deep property or array property of an object in JavaScript you need to use isModified method in order to tell Mongoose that a property of the object is modified and update it in the database.
http://mongoosejs.com/docs/api.html#document_Document-isModified
So you need to execute it after the push function like that:
toUser.isModified('messagesArray')

Related

Node.js & MongoDB not reading variable correctly

Recently, I changed key of object in MongoDB.
{
links: {
changed: 'value',
notchanged: 'value'
}
}
This is what I get from my MongoDB collection. Data which key is not changed is still readable by links.notchanged but data which key is changed like links.changed is not readable and only outputs undefined. Node.js gets and reads the whole links data correctly but when it comes to links.changed it doesn't. How do I solve this problem? Code below:
scheme.findOne({}, (err, data) => {
if (err) res.send('ERR')
else {
console.log(data) // prints full data, same as JSON above
console.log(data.links.changed) // undefined
}
}
You are matching {class:'210'}.. Is it available in document. Probably Your query returns empty object in data . Confirm the match query... Otherwise your code seems ok.
await db1.findOne({class: "210"}, (err, data) => {
console.log(data.links.changed) // returns value
})
Or Try the code like this
await db1.find({ class: "210" }).toArray()
.then(data => {
console.log(data[0].links.changed) //"value"
});
You should make a variable instead of an object for this. For example: Use changed and assign it value as true or false

CoreMongooseArray to Normal Array

I'm shortlisting the 2 elements from one schema and want to update in another schema. for that i used slice method to shortlist first 2 elements from an array. but am Getting
CoreMongooseArray ['element1','element2']
instead of ["element1", "element2"]
How do i remove "CoreMongooseArray" ?
connection.connectedusers.find({}, async (err, docs) => {
if(err) throw err;
var users = docs[0].connectArray;
if (docs[0] != null && users.length >= 2) {
var shortListed = users.slice(0, 2);
try {
await connection.chatschema.updateMany({}, { $push: { usersConnected: [shortListed] } }, { upsert: true });
} catch (err) {
res.status(201).json(err);
}
}
You need to add lean() to your query.
From the docs:
Documents returned from queries with the lean option enabled are plain javascript objects, not Mongoose Documents. They have no save method, getters/setters, virtuals, or other Mongoose features.
If you already got the mongoose array and like to convert to simple js array
const jsArray = mongooseArray.toObject();
https://mongoosejs.com/docs/api/array.html#mongoosearray_MongooseArray-toObject
For some reason .toObject() didn't work for me. lean() option works, but it's not suitable when you already have an object with mongoose array in it. So in case if you already have mongoose array and you want just to convert it to plain js array you can use following code:
function mongooseArrayToArray(mongooseArray) {
const array = [];
for (let i = 0; i < mongooseArray.length; i += 1) {
array.push(mongooseArray[0]);
}
return array;
};
usage:
const array = mongooseArrayToArray(mongooseArray);
If you just want to convert the CoreMongooseArray to a normal array without changing anything else:
const jsArray = [...mongooseArray];

Need help on how to store a value from a MongoDB field into a variable

I want to get the size of the array in my DB so I can loop through it, so I created a field called Size in my DB. I want to store the value of this field in a variable so I know how many times I need to loop through the array. I am able to print out the whole document, but I cannot single out the Size value.
Here is my DB document:
_id:ObjectId("5c02492d1c9d440000498a9b")
Names:Array
Size:5
Now, this is my code that I am trying to extract the number 5 from the size field.
var cursor = db.collection('Room').find('Size');
cursor.forEach(function (err, num) {
if(err) {
return console.log(err);
}
console.log(num);
});
This is what console.log(num) prints:
{ _id: 5c02492d1c9d440000498a9b,
Names:
[ 'TjAa0wOe5k4',
'Sz_YPczxzZc',
'mM5_T-F1Yn4',
'En6TUJJWwww',
'5T_CqqjOPDc' ],
Size: 5 }
Any ideas/help?
For anyone who is wondering, I figured it out. It turns out that turning the result into an array and then calling numArr[0].Size works. Here is the code for anyone curious:
var length;
db.collection('Room').find({'Size': Object}).toArray((err, numArr) => {
if(err) {
return console.log(err);
}
length = numArr[0].Size
return length;
});
Update:
OP fixed it by converting the cursor to an array using .toArray() method and then referencing the property like numArr[0].Size.
You can access the Size property like this:
var size = num.Size;
Have you tried it this way?

MongoDB Async - Find or create docs; return array of them

This is likely a simple answer but I'm relatively new to asynchronous programming and I'm looking for somebody to point me in the right direction.
My question is this - What is the best way to go about finding or creating a number of documents from an array of names (I'm using Mongoose) and then returning an array of _id's?
So to be clear, I want to:
Given an array of names, find or create a document with each name
Return an array of the existing or newly created documents _ids
You can use async module and within it it's async.parallel() method -
https://github.com/caolan/async#quick-examples
async.parallel([
function(){ ... },
function(){ ... }
], callback);
Or you can use promises and then Q.all() to get the array of ids back -
https://github.com/kriskowal/q#combination
Q.all(arrayOfFindOps).then(function(rows) {
return _.pluck(rows, '_id')
}
If you don't want to use any of the above and do it with callbacks, then you have to keep track of the count of array length, keep adding the ids to an array and when your completion counter reaches array length, call another function with the array you made.
This code can be easily modified to meet your requirements. Call this function for each document that required to be created if doesn't exist.
function(req, reply) {
// return document. if not found, create docuemnt.
docModel.findOne( {'name': req.params.name}, function ( err , doc) {
if(err){
//handle error
}
if(doc===null){
//find failed, time to create.
doc = new docModel( {'name': req.params.name} );
doc.save(function(err){
if(err){
//handle error
}
});
}
return reply(user._id);
});
}

mongoose - 'save' method does not exist

Consider a mongodb collection running on MongooseJS.
Sample Code:
Person.where('uid').equals(19524121).select('name').exec(function(err, data){
// Here I can get the data correctly in an array.
console.log(JSON.stringify(data));
data[0].name = "try to save me now"; // Select the first item in the array
data[0].save(); // Object #<Promise> has no method 'save'.
}
Error - Cant seem to figure out a way to fix this.
Object #<Promise> has no method 'save';
I am a little confused on why this is happening and I have researched quite a bit and can't seem to find a direct answer for this.
The result of a find is an array of records. You probably meant to loop over those records like this:
Person.find({ uid: /19524121/ }).select('name').exec(function(err, data){
for(var i = 0; i < data.length; i++) {
var myData = new Person(data[i]);
myData.name = "try to save me now";
myData.save(); // It works now!
}
}
Also, from the mongoose homepage, it appears that the function callback prototype is function(err, data), not the other way around, which you corrected above.
Look at this from the homepage:
var fluffy = new Kitten({ name: 'fluffy' });
If data[0] currently has a regular JSON object, we need a line like this to convert to a BSON model object.
var myData = new Person(data[0]);

Resources