- What are the differences and connections between Mongoose schemas and models? How do they work together in an Express.js application?
- How does Mongoose handle data validation? Discuss the benefits of using Mongoose for data validation as opposed to doing it manually in your Express.js routes.
- What are virtuals in Mongoose? Discuss how and why you might use them in a project. Give examples of scenarios where virtuals can be particularly useful.
- What is population in Mongoose? How does it differ from simply storing object IDs in your documents? Discuss scenarios where population is beneficial and when it might be better to avoid it.
- How does Mongoose handle asynchronous operations? Discuss the role of promises and async/await in managing database interactions in an Express.js application.
-
-
Save halitbatur/4cbcffefc44e4d2f73520dc9b7f52b8d to your computer and use it in GitHub Desktop.
mohmmad smadi , Ammar Kolko , Farah Arar m hakeema alzaidanin:
Q1 : Mongoose schemas define the structure of your data, and models provide an interface to interact with the MongoDB database based on that schema. In an Express.js application, you connect to the database, define your models, and then use those models in route handlers or controllers to perform database operations.
Q2: 1- Validation is defined in the SchemaType
Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default.
Validation always runs as the first pre('save') hook. This means that validation doesn't run on any changes you make in pre('save') hooks.
You can disable automatic validation before save by setting the validateBeforeSave option
You can manually run validation using doc.validate() or doc.validateSync()
You can manually mark a field as invalid (causing validation to fail) by using doc.invalidate(...)
Validators are not run on undefined values. The only exception is the required validator.
When you call Model#save, Mongoose also runs subdocument validation. If an error occurs, your Model#save promise rejects
Validation is customizable.
2- Mongoose offers several benefits over manual validation in Express.js routes:
Schema Definition:
Mongoose allows you to define a schema for your data models, specifying the structure, data types, and validation rules. This schema acts as a blueprint for your documents in MongoDB. This helps in maintaining a consistent structure and ensures that the data adheres to the specified format.
Built-in Validators:
Mongoose provides a variety of built-in validators, such as required, min, max, enum, and more. These validators help you enforce constraints on your data at the schema level, reducing the need for explicit validation code in your Express.js routes.
Middleware Hooks:
Mongoose supports middleware hooks, which are functions that execute at various stages of the data lifecycle, such as before validation, before saving, or after removing a document. This allows you to perform additional logic, transformations, or validations easily, ensuring data consistency.
Error Handling:
Mongoose simplifies error handling by providing a standardized way to catch and handle validation errors. When a validation error occurs, Mongoose returns an error object that can be easily inspected and managed in your Express.js routes.
Consistency Across Routes:
By centralizing data validation in Mongoose schemas, you ensure consistency across different routes and endpoints in your application. This reduces redundancy and makes it easier to manage and maintain your validation logic.
Saves Development Time:
Using Mongoose for data validation saves development time as it abstracts away much of the boilerplate code needed for manual validation. This allows developers to focus more on building features and less on writing repetitive validation code.
Integration with Middleware:
Mongoose integrates seamlessly with Express.js middleware. You can use middleware functions to handle validation, ensuring that validation logic is applied before processing the request further in your route handlers.
Q3: Virtuals in Mongoose are used to create additional properties on your data models without storing them in the actual database. They are handy for calculating or formatting data, improving code organization, and making your code more readable and consistent. Essentially, they help keep your database clean and your code modular.
const userSchema = mongoose.Schema({
email: String
});
// Create a virtual property domain
that's computed from email
.
userSchema.virtual('domain').get(function() {
return this.email.slice(this.email.indexOf('@') + 1);
});
const User = mongoose.model('User', userSchema);
const doc = await User.create({ email: '[email protected]' });
// domain
is now a property on User documents.
doc.domain; // 'gmail.com'
Q4: "population" refers to the process of automatically replacing specified paths in a document with documents from other collections. This is achieved by using references to documents in another collection, rather than embedding the actual documents in the current one.
- When you store object IDs in your documents, you create a reference to another document without embedding the entire document.
Population is the mechanism by which Mongoose can fetch the referenced documents and replace the object IDs with the actual documents during query execution.
-Beneficial:
Reducing Redundancy: Avoid duplicating related data by referencing and populating to store information once and reference it elsewhere.
Consistency: Ensure up-to-date data retrieval for frequently changing information referenced in many documents.
Performance: Improve efficiency by using references and population for large datasets, preventing the impact of large embedded documents on performance.
Avoid:
Small Datasets: Opt for embedding if related data is small and infrequently changed to enhance efficiency.
Read Performance: Choose embedding for frequent reads with minimal latency, accepting some redundancy to avoid additional queries.
Complex Queries: Steer clear of population for applications with complex queries spanning multiple collections to prevent performance issues from multiple queries.
Q5 : callback, promises , Async/sync
promises : Promises provide a cleaner way to handle asynchronous code compared to callbacks, especially when dealing with multiple asynchronous operations
Async/await: allowing you to write asynchronous code in a synchronous style Async/await makes the code more readable and resembles synchronous code, making it easier to understand the flow of asynchronous operations
Team: Fda, Noor, Momena
Q1: A Mongoose model is a wrapper on the Mongoose schema. A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records,
Q2-a customizable middleware that gets defined inside the Schema Type of Mongoose schema. It automatically fires off before a document is saved in the NoSQL DB , Type of validation ( Built-in validation ,Custom validation), the benefit is that it has a built in validation and Error Handling the cabiblity of defining Default Values which lead to more code organization.
Q3- is feature that allow you to define a property on document that is not stored in MongoDB . Virtuals are typically used for computed properties on documents. , let's say we have a User model. Every user has an email, but you also want the email's domain. For example, the domain portion of '[[email protected]]' is 'gmail.com'. Below is one way to implement the domain property using a virtual. You define virtuals on a schema using the [Schema#virtual() function]
Q4-Population is the process or method of automatically replacing the specified paths in the document with document(s) from other collection(s).is a method used to automatically replace the _id or id fields of a document with the a document from another collection. when can use to a void data duplication so we can use reference to another document to have consistency in data so updates apply on places . avoid population when we have Frequency of Updates to avoid heavy database operation and effect on performance
Q4- part 2 . store only the object ID, don't have access to the actual data of the referenced document. if you want to display the data of the referenced document, you'll need to perform an additional query to retrieve it.
Populating the referenced document, allows you to automatically replace the object ID with the actual data of the referenced document.
This means that you can retrieve all the data you need in a single query.
Q5-
Mongoose uses promises to handle asynchronous operations. Promises are a way to handle asynchronous operations in JavaScript, and they provide a way to handle errors and return values in a consistent and predictable way. using .then() and .catch() methods , Mongoose functions that return Promises can be used with async/await, providing a more synchronous code structure.
Room 1: Belal, Musab, Hassan, Mohammad Abdullah
1. What are the differences and connections between Mongoose schemas and models? How do they work together in an Express.js application?
Schemas
A Mongoose schema defines the structure of the document, default values, validators, etc., within a MongoDB collection. It's a blueprint for how your data should look. a schema answers "what will the data in this collection look like?"
Models
A Mongoose model is a wrapper on the Mongoose schema. A Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc. You can think of a model as a constructor which takes in plain JavaScript objects, then adds methods and hooks to them for interacting with the database. a model provides functionality like "Are there any records matching this query?" or "Add a new document to the collection"
2. How does Mongoose handle data validation? Discuss the benefits of using Mongoose for data validation as opposed to doing it manually in your Express.js routes.
- Validation is defined in the SchemaType in mongoose. Validation is a middleware in mongoose.
- Using Mongoose for validation we can define validation rules in the schema, ensuring consistency.
- It simplifies route handlers by abstracting away the validation logic.
- Mongoose validation reduces code duplication. Without Mongoose validation, we have to manually validate data every time before saving it, which can lead to a lot of duplicated code if you're saving data in multiple places in your application.
- Error handling is connected by default with validation in mongoose. When a validation fails, Mongoose will return an error detailing what went wrong.
3. What are virtuals in Mongoose? Discuss how and why you might use them in a project. Give examples of scenarios where virtuals can be particularly useful.
In Mongoose, a virtual is a property that is not stored in MongoDB. Virtuals are typically used for computed properties on documents. They are typically used for computation based on the values of other fields. They are defined on the mongoose schema.
Use cases:
- to format the data in a way that's more convenient for the application. For example, combining firstName and lastName into fullName as shown above.
- for complex calculations. if you have a schema for a product with price and tax fields, you could use a virtual to calculate the total price.
- A common use case for virtuals is to create a virtual field for a password in a user schema. When the password is set, a hashing algorithm can be used to store a hashed version of the password in the database, while the plain text password remains as a virtual and never gets stored.
4. What is population in Mongoose? How does it differ from simply storing object IDs in your documents? Discuss scenarios where population is beneficial and when it might be better to avoid it.
Population in Mongoose is a feature that replaces ObjectIDs in a document with the actual data from the referenced documents, similar to a JOIN operation in SQL. This feature allows you to work with related data as if it was embedded directly into the document, simplifying your code and enhancing readability.
5. How does Mongoose handle asynchronous operations? Discuss the role of promises and async/await in managing database interactions in an Express.js application.
mongoose operations by default are asynchronous because they return promise whenever they get called. we can handle returned promise with .then()
and .catch()
or use async/await to make the code more concise.
Overall, promises and async/await are fundamental in managing database interactions in an Express.js application with MongoDB. using promises or async methods achieves a clean and manageable way to handle asynchronous operations, making it easier to work with the database and handle errors effectively.
Najwan Shawareb, Rinad Abu Qauod, Hadeel Obaid.
1-In an Express.js application using Mongoose:
Schema: Defines the structure of data in a MongoDB collection.
Model: Represents a compiled version of a schema, providing an interface for interacting with MongoDB.
Working Together: Schemas define data structure, models offer methods to interact with MongoDB. In routes or controllers, you use models to perform database operations.
2-Mongoose Data Validation:
Definition: Mongoose allows validation rules to be defined within the schema for each field.
Automatic Validation: Mongoose automatically validates data against the schema during operations like create or save.
Benefits:
Centralization: Rules are defined in one place (the schema).
Consistency: Ensures uniform validation across routes using the same model.
Error Handling: Provides detailed error messages for effective debugging.
Avoiding Redundancy: Reduces manual validation in each route, making the code cleaner.
Using Mongoose for validation simplifies code maintenance, promotes consistency, and enhances error handling in Express.js applications.
3-Virtuals in Mongoose:
Definition: Fields not stored in MongoDB but computed on-the-fly.
Example:
javascript
Copy code
userSchema.virtual('fullName').get(function () {
return this.firstName + ' ' + this.lastName;
});
Use Cases:
Derived Data: Simplifies manipulation of data.
Presentation Formatting: Formats data for presentation.
Avoiding Redundancy: Computes values dynamically, reducing stored data.
Integration with External Data: Incorporates external data on-the-fly.
Security: Excludes sensitive information in responses.
Virtuals offer flexibility and efficiency in handling computed or formatted data in Mongoose schemas.
4-In Mongoose, population refers to the mechanism of automatically replacing specified paths in a document with documents from other collections. It allows you to reference documents from another collection in a more readable and convenient way.
Differences from Storing Object IDs:
-Readability:
Population improves the readability of your code.
-Data Integrity:
Population helps maintain data integrity by ensuring that the referenced documents exist. It allows for easier validation and handling of non-existent or deleted references.
-Mongoose population provides a more convenient and readable way to work with related documents in different collections, reducing redundancy and improving code maintainability compared to simply storing Object IDs.
*Scenarios where Mongoose Population is Beneficial:
Reducing Data Redundancy, Updating Related Documents, When a document references multiple collections.
*Scenarios to Avoid Mongoose Population:
Small Embedded Documents, High Query Volume, Network Latency Concerns, Security Concerns, Document Size Limitations, Read-Heavy Operations.
5- Mongoose, being a MongoDB ODM (Object-Document Mapper) for Node.js, relies on asynchronous operations to interact with the database. It utilizes promises, and supports async/await for handling these asynchronous tasks in a more readable and concise manner
Promises in Mongoose:
Mongoose methods generally return promises. This allows you to use the .then() and .catch() syntax for handling asynchronous operations.
-Async/Await in Mongoose:
With the introduction of async/await in JavaScript, Mongoose allows developers to write asynchronous code that looks more like synchronous code.