Update date inside mongoose schema every time - javascript

I'm trying to update the lastMessageAt every time the [messageSchema] is updated.
It doesn't work this way. I The only date that is generated when the messageSchema is filled with it's very first object.
How do i solve this?
Thanks in advance!
const chatSchema = new mongoose.Schema({
userName1: String,
userName2: String,
messages: [messageSchema],
lastMessageAt: {
type: Date,
default: Date.now
}
});

You could use mongooses post middleware.
chatSchema.post('save', function(next) {
if (this.isModified('messages')) {
this.lastMessageAt = Date.now();
}
next();
});

found out that mongoose now has built in timestamps and they are used like this:
const chatSchema = new mongoose.Schema(
{
userName1: String,
userName2: String,
messages: [messageSchema]
},
{ timestamps: true }
);

Related

Typescript export default always executing

As a beginner in node js I cannot wrap my head around following problem.
import { createSchema, Type, typedModel } from "ts-mongoose";
const CompanySchema = createSchema(
{
companyName: Type.string({ required: true, unique: true })
},
{
timestamps: true
}
);
const Company = typedModel("Company", CompanySchema);
export { CompanySchema, Company };
This all works just fine until one point. When attempting to import this file.
import {CompanySchema, Company} from "./Company";
It executes typeModel method and stores the schema as expected. However, any other import of this file Company.ts reruns this method typeModel again. Which then fails because I can register schema with the name only once. How could I prevent of reruning this and still keep access to this object?
What would be general approach to this in order to keep access to both CompanySchema and Company object(as they will be later used in another schema as a reference)?
I don't know what the createSchema and typedModel are( if they are functions created by you or part of mongoose, the versions of mongoose ive worked with didnt have these functions )
...but I think you should not "createSchema" but define it instead.
e.g
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// define schema
const messageSchema = Schema({
sender: { type: Schema.Types.ObjectId, ref: 'User' },
recipient: { type: Schema.Types.ObjectId, ref: 'User' },
createdAt: { type: Date, default: Date.now },
deletedAt: { type: Date, default: undefined },
readAt: { type: Date, default: undefined},
message: { type: String, maxlength: 5000 }
});
// create a model based on that schema
const Message = mongoose.model('Message', messageSchema);
// Export the message model ... not the schema
module.exports.Message = Message;

Is it possible to define fields at the schema level that are calculated from another field using mongoose?

Is it possible to define fields at the schema level that are based off of another field using mongoose schemas?
For example, say I have this very simple schema:
const mongoose = require('mongoose')
const { Schema } = mongoose
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
username_lower: {
type: String,
// calculated: this.username.toLowerCase()
},
email: {
type: String,
required: true,
unique: true
},
email_lower: { // for case-insensitive email indexing/lookup
type: String,
// calculated: this.email.toLowerCase()
},
password: {
type: String,
required: true
},
password_acceptable: {
type: Array,
// calculated: [
// this.password.toLowerCase(),
// this.password.toUpperCase()
// this.password.removeWhiteSpace(), // just an example
// ]
}
})
const User = mongoose.model('User', UserSchema)
module.exports = User
Is there something similar to the dummy "calculated" fields (that I've commented out) that would allow automatic field creation when the new document is saved? This would be very convenient and would reduce the clutter from having to manually define these fields on my back-end routes.
Thank you very much for your help!
you can do it by Pre middleware function, for more details
UserSchema.pre('save', function(){
this.username_lower = this.username.toLowerCase();
this.email_lower = this.email.toLowerCase();
// and so on ...
next();
});

How to nest schemas in mongoose?

I'm trying to nest schemas using mongoose, but i got stuck and i don't really know why. Here is what i got.
My parent schema
const Comment = require("./Comment");
const BookSchema = new Schema({
_id: Number,
comments: [{ comment: Comment }],
ratings: [{ rate: Number }],
calculatedRating: Number
});
module.exports = Book = mongoose.model("book", BookSchema);
and child schema
const CommentSchema = new Schema(
{
userName: String,
rating: Number,
body: String,
submit_date: {
type: Date,
default: Date.now
}
},
{ _id: false }
);
module.exports = Comment = mongoose.model("comment", CommentSchema);
And with this setup im getting an error :
"TypeError: Invalid schema configuration: Model is not a valid type
at path comment."
I'm considering that i did something wrong with those exports but I'm not sure.
Your ./Comment should be:
const CommentSchema = new Schema(
{
userName: String,
rating: Number,
body: String,
submit_date: {
type: Date,
default: Date.now
}
},
{ _id: false }
);
module.exports = CommentSchema;
If you define as a new model as you did then it will create it's own collection and will be a new model instead of a sub document schema.

The same default value gets used every time by `new mongoose.Schema`

I have problem using uuid with new mongoose.Schema. I use it to generate unique key for a device and save it to the MongoDb using Node.js. the problem is that it uses the same UUID every time.
This is the model:
const mongoose = require('mongoose');
const uuid = require('uuid/v4');
const DeviceSchema = new mongoose.Schema({
deviceNumberHash: {
type: String,
required: true
},
receivingKey: {
type: String,
default: uuid()
}...
});
And this is what is saved in MongoDb:
Any idea what's wrong?
You're calling uuid and passing its return value in as the default to use.
Instead, pass in the function (by not putting () after it):
const DeviceSchema = new mongoose.Schema({
deviceNumberHash: {
type: String,
required: true
},
receivingKey: {
type: String,
default: uuid // <========== No ()
}...
});
The default can be a function per the docs (an example there uses default: Date.now to provide a default for a date field, for instance).

Array of ObjectIds will not populate without error

I have the following mongoose schema:
var ChatSchema = new Schema({
pin: String,
users: [{type: mongoose.Schema.Types.ObjectId, ref: "User"}],
messages: [{type: mongoose.Schema.Types.ObjectId, ref: 'Message'}], //<----
active: Boolean,
});
var MessageSchema = new Schema({
sent: Date,
user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
content: String
});
var UserSchema = new Schema({
name: String,
pin: String,
id: String
});
This function is defined for the ChatSchema:
ChatSchema.methods.addMessageForUser = function(message, userid, userpin ) {
chat = this;
module.exports.User.findOne({id: userid, pin: userpin}).populate('messages').exec(function(err, user) {
message = {
user: user,
time: new Date(),
message: message,
};
chat.messages.push(message);
chat.save();
});
};
When I run it, I get the following error:
CastError: Cast to ObjectId failed for value "[object Object]" at path "messages"
If I remove populate('messages);` Then the error goes away, but I get another error because I try to use the messages array.
Here is the code for the models:
module.exports.Message = mongoose.model('Message', MessageSchema);
module.exports.User = mongoose.model('User', UserSchema);
module.exports.Chat = mongoose.model('Chat', ChatSchema);
Based on what you've got here, you're trying to populate backwards.
If each User had an array of Messages, then this populate call would work. It's a method on the mongoose Query object, in this case, and so it's looking for a property called messages on the documents in the User collection you're querying to pull ids from - since these aren't there, you get a weird error.
Based on what you've got here, it looks like it will work if you just remove the populate call.

Categories