Perform push and pull together in mongodb through mongoose Expresss - node.js

I have been caught in a situation where I have to perform push and pull together.
I have Schema of categories and posts where Posts can have multiple categories and Categories will have array of multiple posts using Object Referencing method of mongoose like this-
PostSchema= new mongoose.Schema({
title:{type:String, required:true},
content:{type:String, required:true},
categories:[{type:mongoose.Schema.Types.ObjectId, ref:'Categories'}]
})
Same way I have set up Schema for categories-
CatSchema = new mongoose.Schema({
name:{type:String, required:true},
slug:{type:String, required:true},
posts:[{type:mongoose.Schema.Types.ObjectId, ref:'Posts'}]
})
Now When I create a post, I push postId in all categories of Categories collection.
But PROBLEM OCCURS when I try to UPDATE POST AND CHOOSE DIFFERENT CATEGORIES from earlier this time.
I can still push updated postId in newly selected categories but How do I pull postId from those categories which are not selected during update but selected during creation. They still store this postId as it was initially pushed.
In clearer, I want to update posts array in categories collection whenever update a category. All types of solutions are welcome including better approach of creating schema or solving this particular problem.
Thanks

I understand that for this update you require postID, arrayOldCaretoryiesID, and arrayNewCategoriesID.
Let's find and remove from the current post the category you need.
const deletedCatFromPost = await Post.updateOne({ _id: postID }, { $pull: { categories: arrayOldCaretoryiesID } })
Second, remove from old categories by an array of IDs the post you need.
const removedOldCategories = await Categories.updateMany({_id:{$or: arrayOldCaretoryiesID }},{ $pull:{ posts: postID }})
Finally, add to new categories by an array of IDs a new postID.
const addNewCategories = await Categories.updateMany({_id: { $or: arrayNewCategoriesID} },{$push:{ posts: postID }})
Hope this can help you.
Update:
Second, remove from old categories by an array of IDs the post you need.
const removedOldCategories = await Categories.updateMany({_id:{$in: arrayOldCaretoryiesID }},{ $pull:{ posts: postID }})

Related

delete records from multiple collections on the basis of value present in MainCollection (mongoose) Express.js

Hello everyone I'm new to mongo and i'm stuck on something. I'm creating a expense tracker using react.js express.js and mongodb.
I've 2 collections : TrancstionSchema
const schema = mongoose.Schema({
title: String,
createdDate: Date,
amount:Number,
expenseType:String,
category:String
})
Category Schema
const schema = mongoose.Schema({
title: String,
createdDate: Date,
})
If user delete a Category it should remove it's records from Category schema and transactions schema
as you can see that Category List title is referenced to transactionList as a category
**
If User delete a category it record should be deleted from both
collections categoryList and transaction list .
** Please help with a code sample
You can define a middleware function to run automatically after your category schema remove operation:
// Category schema
const schema = mongoose.Schema({
title: String,
createdDate: Date,
})
schema.post('remove', async (doc, next) => {
// Delete all records from transaction schema with category
await Transaction.deleteMany({ category: doc.title })
// OR Update the category of transactions to empty string
await Transaction.updateMany({ category: doc.titleĀ }, { category: '' })
next()
})
Calling the remove function on a category document will automatically delete all transaction with the same category associated:
await category.remove();

How to query sub subdocument using mongoose?

let say i have a schema like this:
const Product = mongoose.schema({
product_id: uuid,
product_quantity: number,
})
const Customer = mongoose.schema({
customer_id: uuid,
customer_cart: [product],
})
const Store = mongoose.schema({
store_id: string,
customers: [customer],
})
how can I query the product if i have the store_id ,customer_id and the product_id?
I know i can query it by get back all store document and use loop to loop through the object array.
But i think it will be very slow if the store have many customer and customer have many product in their cart.
Is there a way to just get back the product without get back the whole store document?

Populate in mongoose returns array of _ids

I'm creating simulation for goodreads by MERN stack
and when I'm using populate to retrieve books of specific user it returns empty array, I've done a lot of search but in vain
here's my model
const userSchema =new mongoose.Schema({
firstName:{
type:"string",required:true
},
books:[{
book:{type:mongoose.Schema.Types.ObjectId,ref:'Book'},rate:Number,shelve:''
}]});
And this is books model
const bookSchema =new mongoose.Schema({
title :{
type:"string",required:true
}});
And this is how I use populate
router.get("/one", (req, res, next) => {
User.find({firstName : "John"}).populate("books.book").exec(function (err, user) {
res.json(user)
});
})
and this is the resulted JSON
[{"_id":"5c70f299ef088c13a3ff3a2c","books":
[{"_id":"5c708c0077a0e703b15310b9"},{"_id":"5c708c0077a0e703b15310ba"},
{"_id":"5c708c0077a0e703b15310bb"},{"_id":"5c708c0077a0e703b15310bd"}]}]
I believe it's an issue with how your UserSchema is defined. My assumption is that including the rate and shelve in the definition of books is causing the problem.
Try removing those fields to start, and just populating books instead of books.book. If that works, then I would really reconsider putting those fields where you have them. In my own personal opinion, I think they seem better in the BookSchema since each book in the UserSchema has a rate and shelve anyways. Hope this helps!!

Mongoose distinct query

Excuse my ignorance but it is possible to get distinct tag attribute with all the links in one query?
I know you can using .distinct('tag') but then I need to send the data twice which require querying the same link again
I have the following schema
var Link = new Schema({
title:{type:String, required:true},
url:{type:String, required:true},
tag:[{type: String,required:true}],
});
link
.find({})
.exec(function(err,q){
res.json(q);
});
In case you need all URLs per tag:
db.link.aggregate({
$group : {
_id : "$tag",
links: { $addToSet: "$url" }
}
})

How to declare schematype/datatype of a field in mongoose which is the objetid of an item in another collection?

I am a bit confused by something in MongoDB, when using Mongoose, since I am new to it. I have two collections: authors and posts.
each author in the authors collection have the mongodb inbuilt id associated with them, which as per my understanding is of the schematype/datatype Objectid.
Now in my posts collection, I have a field which has is called author, which should have the value of the author's Objectid, similar to the foreign key concept in SQL.
My question is, which schematype/datatype should I declare the author field in the posts collection? Should I put it as Objectid? If so, would it not auto-increment and not be settable?
Mockup Of Schemas:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: **??**
});
Any help would be hugely appreciated!
You can use population for that:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: { type: Schema.Types.ObjectId, ref: 'Author' }
// assuming the model will be called 'Author'
});
To use:
// Get 'author' some how (create a new one, query the
// database for existing authors, etc);
...
// Create a new post and associate it with 'author' by referencing its `_id`:
var post = new Post({
...
author : author._id
});
post.save(...);
The documentation linked above also shows how you can get Mongoose to automatically retrieve the author document when you're querying posts.

Resources