mongoose - perfroming CRUD operations on a sub document - mongodb

I'm creating a mern app, and pretty new to mongodb and mongoose, and I'm currently struggling with the concept of the subdocument in mongodb and how to perform crud operations in express. I've been researching and haven't found many tutorials or articles on subdocuments, mostly the referenced documents and population.
I have two separate schemas
var ProjectSchema= new mongoose.Schema({
title:{
type:String,
required:true,
unique:true
},
description:String,
lists: [ListSchema]
})
var ListSchema= new mongoose.Schema({
name: {
type:String,
required:true
}
})
Currently, i'm trying to insert data into the List schema.
listRouter.post('/api/project/:projectId/list/new', asyncMiddleware(async function(req,res,next){
Project.findById(req.params.projectId, await function(err,items){
items.lists.push(req.body)
items.save();
res.json(items)
})
}))
What happens is that the data are inserted into the Project.lists but when I check the List collection in mongodb, it's empty.
From my reading the sub documents documentation , it stats you can't save the sub documents individually, you have to do via the parent document- which I have in the code above.
Doesn't the List collection supposed to automatically get the new data after saving the Project document? Or something else is happening? Any input would be appreciated.

Related

Is it fine to use javascript sort instead of mongoose sort?

I have a messaging app, and a route to fetch a user's messages. A user can have 1000+ threads. I use Mongoose and Express.
I basically find a user by id, populate its messages array, and then apply a reverse() on it so it displays all the threads from new to old. I do it because I don't know how to sort a populated field. Is it fine to use native js instead of mongoose sort method form a performance point of view?
const user = await User.findById({ _id: userId }).populate("messages");
return res.json({ messages: user.messages.reverse() });
If it's crap, how to sort such a populated field?
if you want to sort in order of creation you can use the _id field of each message. MongoDB treats sorting by _id the same as sorting by creation time. So your mongoose query would look like:
const user = await User
.findById({ _id: userId })
.populate({path: 'messages', options: { sort: { '_id': -1 } } });
return res.json({ messages: user.messages });
I am not quite sure as to the performance comparison of sorting using JS or Using mongoose though...

Query generated mongo-version collection without model

I want to use mongoose-version to track and keep changes in mongodb.
I created this example schema.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var version = require('mongoose-version');
var PageSchema = new Schema({
title : { type : String, required : true},
tags : [String],
});
PageSchema.plugin(version, { collection: 'Page__versions' });
const PageModel = mongoose.model('PageModel', PageSchema)
So all versions are stored in collection Page__versions, but how can I query this collection, because I don't have a model for that collection.
To get the collection you can use the mongoose database object that is returned from the createConnection function. So when you start the application you store this variable like this
let db = mongoose.createConnection(url, params);
And then you can use this object to get the collection you want, in this case
let collection = db.collection("Page__versions");
At this point you can use the standard methods to do CRUD operations on that collection, for example if you want to find all documents that have a specific property in that collection, you can do something like this
collection.find({myProperty: value});
And this will give you all documents that are in that collection that matches the criteria.
If you don't know the model you can always get one item from the collection and see what the result is
let doc = collection.findOne({}); //This will get the first document in the collection

Mongoose query document by field value and subdocument field value

I'm using mongoose and trying to get document by specific value of field on it and subdocument field's specific value. I dig a lot but I was unable to find anything matching - I am also new to MongoDb.
So my schema looks like :
messageSchema = Schema candidateId: {type: string},
template: {type: Schema.Types.ObjectId, ref: 'MessageTemplate'},
messageTemplate = Schema name:{type: string}, isActive:{type: boolean}
So I want to get all messages that have certain candidateId and messageTemplate.isActive equal to true.
I couldn't figure out query so I am doing work around like this
Message.find({candidateId: candidateId})
.populate('template')
.then(res => res.fileter(message => message.template.isActive)
It's working but I'm guessing it's possible to create better query, any help will be great.

Generating a new Mongo object id for each document in a collection?

How do you go about creating a unique object id for each document in a mass update?
I've tried,
db.foo.update({ objectId: null }, { $set: { objectId: new ObjectId() }}, { multi: true })
But that gives me the same object id for each document.
Because you're applying a unique value to each doc, you need to iterate over your collection and update the docs one at a time.
In the shell:
db.foo.find({ objectId: null }).forEach(function(doc) {
doc.objectId = new ObjectId();
db.foo.save(doc);
});
You cannot update multiple documents in a single command in MongoDb currently. You can update multiple documents with a common set of changes/updates, but you can not make unique changes to each document. You would need to create a loop to iterate over each document in the shell or your favorite programming language.
You can generate an object Id in MongoDB like this. You can iterate over your doc and use this mongo object id.
const ObjectId = require("mongodb").ObjectID;
const id = new ObjectId
console.log(id)

Mongodb querying document with linked id

I have a document that has an id of another document from a different collection embedded in it.
My desired result is to return (I'm using python and pymongo) the all the fields of the first collection, and all of the friends from the document that was embedded.
I understand mongo doesn't do joins and I understand I'll need to make two queries. I also don't want to duplicate my data.
My question is how to piece the two queries together in python/pymongo so I have one results with all the fields from both documents in it.
Here is what my data looks like:
db.employees
{_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Joe Smith', title: 'junior',
manager: ObjectId("4d85c7039ab0fd70a117d730") }
db.managers
{_id: ObjectId("ObjectId("4d85c7039ab0fd70a117d730"), name: 'Jane Doe', title: 'senior manager'}
desired result
x = {_id: ObjectId("4d85c7039ab0fd70a117d733"), name: 'Joe Smith', title: 'junior',
manager: 'Jane Doe' }
Your basically doing something that Mongo does not support out of the box and would actually be more painful than using the two records separately.
Basically (in pseudo/JS code since I am not a Python programmer):
var emp = db.employees.find({ name: 'Joe Smith' });
var mang = db.managers.find({ _id: emp._id });
And there you have it you have the two records separately. You cannot chain as #slownage shows and get a merged result, or any result infact since MongoDB, from one qauery, will actually return a dictionary not the value of the field even when you specify only one field to return.
So this is really the only solution, to get the the two separately and then work on them.
Edit
You could use a DBRef here but it is pretty much the same as doing it this way, only difference is that it is a helper to put it into your own model instead of doing it youself.
If it works it should be something like:
db.managers.find({
'_id' => db->employees->find({ ('_id' : 1),
('_id': ObjectId("4d85c7039ab0fd70a117d733") }))
})
updated