How to query sub subdocument using mongoose? - node.js

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?

Related

How to override mongoose schema

Lets say I have this schema:
const userSchema = new Schema({
name: {type: String},
email: {type: String},
created: {type: Date,default: Date.now},
deleted: {type: Date,default: undefined}
});
And that I add a few rows:
const user1 = new User({name: 'bob',email: 'bob#google.com'});
const user2 = new User({name: 'mary',email: 'mary#google.com'});
const user3 = new User({name: 'alice',email: 'alice#google.com'});
When calling
User.find({});
I will get all three users above.
However, I want add a function to delete them in a soft way. That's why I have the field "deleted".
By doing this:
const user = User.find({email: 'bob#google.com'});
user.deleted = Date.now();
In mongo, the user bob will have the field deleted NOT undefined.
If I now call again this:
User.find({});
Bob will also be delivered. Of course I can add the flag directly like this:
User.find({deleted: undefined});
But if all database wants to apply this principle, I guess it would be better to centrilize this functionality.
Is this about overriding the mongoose schema? Could somebody point me into the right direction here?
If you are doing a find with no filters then it will return ALL records. If you don't want some users (such as those who have a date in the 'deleted' field) then you need to put in a filter.
find({}) is equivalent to select * from table. It returns ALL records without any filter.

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();

Perform push and pull together in mongodb through mongoose Expresss

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

Nested objects are not update

Allora, I'm using mongoose for the first time and I decided to create 2 schemes: the first one represents a user and the second one represents his enquires. Users have an array of enquires like:
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [Enquire.schema] , "default" : [] },
});
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
I see that if I search for an enquire and update its status, it doesn't update the same enquire on the user's array, meaning that they are different object. I don't want to save an array of IDs as it will be the same as a relational database, so I see only 1 solution which is forgetting about the enquire scheme and use only the User scheme. Is it the way mongoose works? For every relationship do I have to insert everything like nested object?
I think you should use references to achieve what you want to achieve.
For more information on mongoose references and populate see Mongoose Populate documentation.
Try this, It may help you.
User Schema :
var userSchema = new mongoose.Schema({
name: String,
enquires: [{ type : mongoose.Schema.Types.ObjectId , ref : 'Enquiry' }]//array of enquiries
});
var User = mongoose.model('User',userSchema );
module.exports = User;
Enquiry Schema :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var Enquiry = mongoose.model('Enquiry',enquireSchema );
module.exports = Enquiry ;
Working :
create a new Enquiry.
Push it's ID(_id) into user's enquires array.
var enquiry = new Enquiry();
enquiry.enquire = "Dummy enquiry";//set the enquiry
enquiry.save(function(err,result){
if(!err){
//push 'result._id' into users enquires array
}
});
whenever you update an enquiry, it will be automatically updated in
user's document.
use populate to retrieve user's enquiries.
You can embed sub documents (entity) which has id and is like a document or embed native array like a normal property.
And I think the correct definition for yours is :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [enquireSchema] , "default" : [] },
});
If you use refs in embedded link then there are two separate collections and be like relational db's.

Store Country, City and User info using mongoose and nodejs MongoDB

I want to use mongodb on my new project. That is first time, im using mongodb. In relational databases i was saving datas like:
tbl_country > id,name,created_at,etc..
tbl_city > id,country_id,name,created_at,etc...
tbl_user > id,name_surname,city_id,etc...
In this schema i can find a city's country, a user's country, etc... via using foreign keys.
Which way do you suggest to create a schema like this in best performance by nodejs w/ mongodb ?
You can still use foreign keys when you create your schemas. Please check this schemas as examples you have given.
var CountrySchema = new Schema({
name: String,
created_at: Date
});
var CitySchema = new Schema({
countryName: { type: mongoose.Schema.Types.ObjectId, ref: 'Country' },
created_at: Date
});
var UserSchema = new Schema({
name_surname: String,
city: { type: mongoose.Schema.Types.ObjectId, ref: 'City' }
})
mongoose.model('Country', CountrySchema);
mongoose.model('City', CitySchema);
mongoose.model('User', UserSchema);
and when you fetch data, you have to use 'populate' method. For instance:
City.find()
populate('countryName', 'name') // It will bring only name field
.exec(function(err, cities) {
})
Btw. _id s are automatically created by mongo for each data. So you do not need to add id field into your schemas. Hope it helps. Good luck

Resources