How to find a document based on the embedded object key value? - mongodb

Using mongoose .findOne() how would you find a document based on the key value that is deep into the object? Like for example how would I find a document based on the meta.votes value?
var blogSchema = new Schema({
title: String, // String is shorthand for {type: String}
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});

Related

Referencing another collection Mongoose (MONGO)

If i have two Schema's as follows;
const userSchema = new mongoose.Schema({
telegramId: Number,
username: String,
balance: { type: Number, default: 0 },
totalTopUp: { type: Number, default: 0 },
totalRefunds: { type: Number, default: 0 },
totalOrders: { type: Number, default: 0 },
joined: Date,
});
const orderSchema = new mongoose.Schema({
orderId: String,
cardId: String,
userId: Number,
refunded: { type: Boolean, default: false },
baseId: String,
price: Number,
date: Date,
});
Where telegramId in userSchema and userId in orderSchema will match when a user makes an order, is it possible to have totalOrders in userSchema automatically update via some sort of referencing. Or will updates to totalOrders need to be made via code.
you can use post('save') middleware over orderSchema, on each new document you can increase the total orders.
https://mongoosejs.com/docs/api.html#schema_Schema-post

Is there a way to know which mongoDB field in a document was updated last?

For example, I would want to know which field was updated last for this schema:
var blogSchema = new Schema({
title: String,
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});
Unfortunately there is no built-in functionality that supports it. You'll probably have to implement the logic yourself.

Get documents with specific value in an array inside the document in mongodb

my document is as below
const mailSchema = new Schema ({
from: String,
to: [{
emailId: String,
status: Number
}],
cc: [{
emailId: String,
status: Number
}],
bcc: [{
emailId: String,
status: Number
}],
subject: String,
content: String,
status: Number,
createdBy: Schema.Types.ObjectId
}
How to retrieve document where 'to.emailid' contains a given value?
I have used below code but it is not working.
const emailtext = 'test#gmail.com'
MailSchema.find({'to.emailId': emailtext });
I think your schema is incorrect. what you want to do is to have a document that contain an object file. But what you did is a document with an array of file objects. so i think you should remove all the square bracket in the schema, then it should look like this.
//Mail Schema without array of objects.
const mailSchema = new Schema ({
from: String,
to: {
emailId: String,
status: Number
},
cc: {
emailId: String,
status: Number
},
bcc: {
emailId: String,
status: Number
},
subject: String,
content: String,
status: Number,
createdBy: Schema.Types.ObjectId
}
However if what you really want is an array of objects, then your query should also include the index of the array you want to get the emailId from.
Example.
MailSchema.find({'to[0].emailId': emailtext });

Mongoose, proper way to update documents with deep nested schemas

I would like to know what would be the most efficient way to update a document that also has a nested schema in it. Normally I would just use Model.findByIdAndUpdate(id, updatedValues) ..., however if I try to do that with a document that has a deep nested schema I get this error: CastError: Cast to Embedded failed for value "{ _id: 5b1936aab50e727c83687797, en_US: 'Meat', lt_LT: 'Mesa' }" at path "title".
My Schemas look something like:
const titleSchema = new Schema({
en_US: {
type: String,
required: true
},
lt_LT: {
type: String,
default: null
}
})
const categorySchema = new Schema({
title: titleSchema
});
const ingredientSchema = new Schema({
title: {
type: titleSchema,
required: true
},
category: categorySchema,
calories: {
type: Number,
min: 0,
default: 0
},
vitamins: [String]
})
And I try to update like so:
{
title: {
en_US: 'Pork',
lt_LT: 'Kiauliena'
},
category: {
_id: '5b193a230af63a7e80b6acd8',
title: {
_id: '5b193a230af63a7e80b6acd7'
en_US: 'Meat',
lt_LT: 'Mesa'
}
}
}
Note, I get the new category object from a separate collection using just the category _id, but the final update object that goes into the findByIdAndUpdate() function looks like the one above.
The only workout I found is to remove the category from the updated values, update the document via findByIdAndUpdate(), get the updated document, assign the new category to it and save it.
It works just fine and all, but that requires two calls to the database, is it possible to do it in just one?
Try updating your schema like this:
const titleSchema = new Schema({
en_US: {
type: String,
required: true
},
lt_LT: {
type: String,
default: null
}
});
const ingredientSchema = new Schema({
title: {
type: titleSchema,
required: true
},
category: {
title: titleSchema
},
calories: {
type: Number,
min: 0,
default: 0
},
vitamins: [String]
});

How do you change a fieldName via mongoose method + change it in schema?

I have a schema like this:
const StorySchema = new Schema({
authorId: String,
title: String,
longUrl: String,
shortUrl: String,
comment: String,
category: String,
author: String,
date: { type: Date, default: Date.now, index: true },
votes: { type: Number, default: 1, index: true },
});
I want to change the votes field on the schema to be called votesCount and at the same time I want to actually change the schema.
Would I just do these in the same file?
const StorySchema = new Schema({
authorId: String,
title: String,
longUrl: String,
shortUrl: String,
comment: String,
category: String,
author: String,
date: { type: Date, default: Date.now, index: true },
votesCount: { type: Number, default: 1, index: true },
});
const StoryModel = mongoose.model('story', StorySchema);
StoryModel.update({}, { $rename: { votes: 'votesCount' } }, { multi: true, strict: false }, function(err, blocks) { });
Or do I not do this at all in the code? I have never dealt with database schema changes, so I'm not sure how / where to apply schema changes.
Make your changes in the Schema and the controller, as whatever name you use in your Schema field should also tally with the one in your Controller.
Eg.
const StorySchema = new Schema({
authorId: String,
title: String,
longUrl: String,
shortUrl: String,
comment: String,
category: String,
author: String,
date: { type: Date, default: Date.now, index: true },
votesCount: { type: Number, default: 1, index: true },
});
In your controller
let form = {
authorId:req.body.*****,
title:req.body.*****,
longUrl:req.body.*****,
shortUrl:req.body.*****,
comment:req.body.*****,
category:req.body.*****,
author:req.body.*****,
date:req.body.*****,
votesCount:req.body.*****
};
Note: the main point am trying to make here is that, the very name you used in the Schema should also the the same name you're gonna use for your controller.
I hope this is answers your question.
best use updateMany as
db.students.updateMany( {}, { $rename: { "nmae": "name" } } )
and change in your controller or directly replace previous field name to new field name where ever possible.
My Suggestion is better u first replace in controller or your project and if your project running in production update your new controller than u replace the field name using $rename