CoreMongooseArray to Normal Array - node.js

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];

Related

Get missing fields on mongoose scheme

I need to get a count of all the missing or empty fields in mongoose schema
The idea is to have a list of all the properties in a mongoose schema that are blank or does not have a value, so I can make a function to know what percentage of the document is missing.
I tried with count and count by null, but i don't know the query to get the results.
You can have a function like this in your application code:
const getDocumentCompleteness = (doc) => {
const totaFieldCount = Object.keys(doc).length;
let completedFieldCount = 0;
for(let key in doc) {
if(doc[key] !== undefined && doc[key] !== null && doc[key] !== '') {
completedFieldCount += 1;
}
}
return [totaFieldCount, completedFieldCount];
}
Whenever you need to get the completeness of a document, you can do this:
const [totaFieldCount, completedFieldCount] = getDocumentCompleteness(document);
// where document is the object representing the document you got from the database
I hope that helps.

Mongoose find not match ids from array which passed

I'm stuck in mongoose query. I've an array of ids as input, I want to search that array of ids in a database for matching elements. It returns perfect result after using $in in find query.
Now, I want that Ids from an array which is not found in the database. what is the best way to do it?
Please try to comment it.
Template.find({
_ids : [
"as6d87as67da7s8d87a87", // available in database
"as6dasd8sa9d8a9a9s8d7", // not-available in database
"6756asd5as6dsadghasd3", // available in database
]
}, function(err, result){
// Need result as "as6dasd8sa9d8a9a9s8d7", which is not matched. or in object.
// Can we do with `aggregate` query?
});
I think this makes what you want
var _ids = [
"as6d87as67da7s8d87a87",
"as6dasd8sa9d8a9a9s8d7",
"6756asd5as6dsadghasd3"
];
Template.find({
_ids : _ids
}, function(err, result){
var filteredResult = _ids.filter(currentId => !result.some(item => item._id.toString() == currentId));
});
Answer by David will work. The idea here is to compare _ids array with the _ids in the result and return the missing ones. Adding more code just for understanding purposes:
Push _id of result into a new array
Compare _ids and the new array to return missing elements
var resIDs = new Array();
for (var i = 0; i < result.length; i++) {
resIDs.push(result[i]._id.toString());
}
var resultFiltered =
_ids.filter(function (v) {
return !resIDs.includes(v.toString());
})

Mongoose: Push data to array in for loop

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

Add an array as a subdocument to a Mongoose model instance

I am building an array with data and want to push that array to sub-document.
var pubArray = [];
var count = 5
for (i = 0; i < count; i++) {
pubArray.push({publicationName: req.body.publicationName[i], dateSent:req.body.dateSent[i]});
};
Students.findOne({studentNumber: filter}, function (err, student) {
student.publications.push({pubArray});
student.save();
});
If I use the {publicationName: req.body.publicationName[i], dateSent:req.body.dateSent[i]} inside the student.publications.push it works fine. If I try to push the array, nothing happens.
Note that the .push() method in mogoose works just like it's JavaScript equivalent in that it is "pushing" a single element onto the array, rather than a whole array. So you can either assign the whole array or just construct in the loop:
student.publications = pubArray;
or:
// Construct with .push in loop:
Students.findOne({ "studentNumber": filter },function(err,student) {
for ( var i = 0; i < count: i++ ) {
student.publications.push({
"publicationName": req.body.publicationName[i],
"dateSent": req.body.dateSent[i]
});
}
student.save(function(err) {
// Complete
});
});
But really you would be better off using an "atomic" operator of $push with $each in a direct update. This is then just one trip to the server, rather than two:
Students.update(
{ "studentNumber": filter },
{ "$push": { "publications": { "$each": pubArray } } },
function(err,numAffected) {
}
);
That is generally worlds better than the "find/modify/save" pattern, and not only in being more efficient, but it also avoids potential conflicts or overwriting data since the object and array is modified "in-place" in the database, with the state current to the time of modification.
Atomic operators should always be favoured for the performance benefits as well as lack of conflicts in modification.
The publications property of the student object is an Array. You can simply assign this property to the pubArray created earlier:
Students.findOne({studentNumber: filter}, function (err, student) {
student.publications = pubArray;
student.save();
});

Loop through Mongo Collection and update a field in every document

I have Dates in one Collection that were inserted incorrectly, and are in a simple "2015-09-10" string format.
I'd like to update them to correct ISO Date format.
I've tried looping through Mongo with forEach() but I don't know the shell well enough on how to update each document in the collection.
So far I'm at this point:
db.getCollection('schedules').find({}).forEach(function (doc) {
doc.time = new Date( doc.time ).toUTCString();
printjson( doc.time );
// ^ This just prints "Invalid Date"
// Also none of the below work when I try saving them
//doc.save();
//db.getCollection('schedules').save(doc);
});
What's missing here?
The best way to do this is using "Bulk" operations
var collection = db.getCollection('schedules');
var bulkOp = collection.initializeOrderedBulkOp();
var count = 0;
collection.find().forEach(function(doc) {
bulkOp.find({ '_id': doc._id }).updateOne({
'$set': { 'time': new Date(doc.time) }
});
count++;
if(count % 100 === 0) {
// Execute per 100 operations and re-init
bulkOp.execute();
bulkOp = collection.initializeOrderedBulkOp();
}
});
// Clean up queues
if(count > 0) {
bulkOp.execute();
}
Just write a for loop using .find(), and update each result. For instance, in Python/PyMongo, let's assume we have a collection called 'movies' that we want to update by adding a field called 'reviews', whose value we want to be an array of five objects with 'name' and 'rating' fields. we'll use Faker and random to create some random info for these fields:
from pymongo import MongoClient
from faker import Faker
faker = Faker()
import random
client = MongoClient()
db = client.test
for res in db.movies.find():
db.movies.updata_one(res, {'$set':{'reviews':[{'name':faker.name(), 'rating': random.randint(1,5)} for _ in range(5)]}})
Note that if you're using native Mongo, then you should be using updateOne instead of update_one. I presume a similar approach works in JavaScript, just using for (let res of db.movies.find()) syntax

Resources