W tej lekcji przyjrzymy się bardziej zaawansowanym możliwościom schematów Mongoose. Nauczysz się, jak dodawać złożone struktury danych, jak korzystać z domyślnych wartości oraz jak tworzyć metody w modelach, które pozwalają na dodanie własnej logiki aplikacji. Wykorzystamy także wbudowane i niestandardowe walidacje, aby zapewnić integralność danych w naszej bazie MongoDB.
Zaawansowane Schematy i Metody
Stwórz nowy plik o nazwie mongoose_advanced.js
i wklej poniższy kod. Wprowadza on różne aspekty zaawansowanej pracy ze schematami i modelami w Mongoose.
Implementacja
// Importujemy Mongoose do naszego projektu
const mongoose = require('mongoose');
// Ustawiamy URL połączenia z lokalną bazą danych MongoDB
const url = 'mongodb://localhost:27017/myAdvancedMongooseDatabase';
// Funkcja główna, w której będziemy wykonywać wszystkie operacje
async function main() {
try {
// Nawiązujemy połączenie z MongoDB za pomocą Mongoose
await mongoose.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log('Połączono z MongoDB za pomocą Mongoose!');
// --- Definiowanie zaawansowanego schematu i modelu ---
// Definiujemy schemat dla kolekcji "products"
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
minlength: [3, 'Nazwa produktu musi mieć przynajmniej 3 znaki'], // Wbudowana walidacja długości
},
price: {
type: Number,
required: true,
min: [0, 'Cena nie może być ujemna'], // Wbudowana walidacja minimalnej wartości
},
category: {
type: String,
enum: ['electronics', 'books', 'home_appliances'], // Akceptujemy tylko określone wartości
default: 'electronics', // Domyślna wartość
},
stock: {
type: Number,
default: 0, // Domyślnie ustawia stan magazynowy na 0
validate: {
validator: Number.isInteger, // Niestandardowa walidacja - pole musi być liczbą całkowitą
message: 'Stan magazynowy musi być liczbą całkowitą',
},
},
createdAt: {
type: Date,
default: Date.now, // Ustawiamy bieżącą datę jako domyślną wartość
},
tags: [String], // Tablica ciągów znaków do przechowywania tagów produktu
});
// --- Dodawanie metod do schematu ---
// Definiujemy metodę na poziomie instancji modelu (każdego dokumentu)
productSchema.methods.applyDiscount = function (percentage) {
// Obniża cenę produktu o określony procent
this.price = this.price - (this.price * (percentage / 100));
return this.price;
};
// Definiujemy statyczną metodę na poziomie modelu (dla całej kolekcji)
productSchema.statics.findByCategory = function (category) {
// Wyszukuje produkty w określonej kategorii
return this.find({ category: category });
};
// Tworzymy model "Product" na podstawie zdefiniowanego schematu
const Product = mongoose.model('Product', productSchema);
// --- CREATE: Dodawanie nowego produktu ---
// Tworzymy nową instancję produktu
const newProduct = new Product({
name: 'Blender',
price: 250,
category: 'home_appliances',
stock: 30,
tags: ['kitchen', 'appliances'],
});
// Zapisujemy nowy produkt w bazie danych
await newProduct.save();
console.log('Nowy produkt zapisany:', newProduct);
// --- READ: Wyszukiwanie produktów przy użyciu metod ---
// Znajdujemy wszystkie produkty w kategorii "home_appliances"
const homeAppliances = await Product.findByCategory('home_appliances');
console.log('Produkty z kategorii "home_appliances":', homeAppliances);
// --- UPDATE: Aktualizowanie produktu za pomocą metody instancji ---
// Obniżamy cenę produktu o 20% za pomocą metody instancji
newProduct.applyDiscount(20);
await newProduct.save(); // Zapisujemy zaktualizowaną cenę w bazie danych
console.log('Zaktualizowana cena po obniżce:', newProduct.price);
// --- Walidacja niestandardowa ---
try {
// Tworzymy produkt z nieprawidłowym stanem magazynowym (ułamek)
const invalidProduct = new Product({
name: 'Invalid Product',
price: 100,
category: 'electronics',
stock: 5.5, // Nieprawidłowa wartość - powinna być liczbą całkowitą
});
await invalidProduct.save(); // Próbujemy zapisać produkt
} catch (validationError) {
console.error('Błąd walidacji produktu:', validationError.message);
}
} catch (error) {
console.error('Błąd podczas operacji na bazie danych:', error); // Obsługa błędów
} finally {
// Zawsze zamykamy połączenie z bazą danych, nawet w przypadku błędu
await mongoose.connection.close();
console.log('Połączenie z MongoDB zamknięte.');
}
}
// Wywołujemy główną funkcję
main()
Jeżeli chcesz przyśpieszyć swoją naukę tworzenia stron chciałbym polecić mój kurs video JavaScript w którym nauczysz się tego języka od podstaw do zaawansowanych jego aspektów.