MongoDB(90)如何使用Mongoose进行ORM操作?

17 阅读3分钟

Mongoose 是一个 MongoDB 对象建模工具,提供了一种在 Node.js 环境中优雅地与 MongoDB 进行交互的方法。它提供了数据验证、查询构建、业务逻辑挂钩等功能。下面详细介绍如何使用 Mongoose 进行 ORM 操作。

一、安装和配置 Mongoose

1. 安装 Mongoose

通过 npm 安装 Mongoose:

npm install mongoose

2. 连接到 MongoDB

创建一个新的 Node.js 文件,例如 app.js,并连接到 MongoDB:

const mongoose = require('mongoose');

const dbURL = 'mongodb://localhost:27017/mydatabase';

mongoose.connect(dbURL, {
    useNewUrlParser: true,
    useUnifiedTopology: true
}).then(() => {
    console.log('Connected to MongoDB');
}).catch(err => {
    console.error('Connection error', err);
});

二、定义 Schema 和 Model

Mongoose 使用 Schema 来定义文档的结构、数据类型、默认值、验证规则等,然后通过 Schema 创建 Model 来操作集合中的文档。

1. 定义 Schema

创建一个新的文件 models/user.js,定义 User Schema:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    age: {
        type: Number,
        required: true
    },
    email: {
        type: String,
        required: true,
        unique: true
    },
    createdAt: {
        type: Date,
        default: Date.now
    }
});

module.exports = mongoose.model('User', userSchema);

三、使用 Model 进行数据库操作

app.js 中使用定义好的 User 模型进行 CRUD 操作。

1. 创建文档

const User = require('./models/user');

// 创建一个新用户
const newUser = new User({
    name: 'Alice',
    age: 25,
    email: 'alice@example.com'
});

newUser.save()
    .then(user => {
        console.log('User saved:', user);
    })
    .catch(err => {
        console.error('Error saving user:', err);
    });

2. 查询文档

// 查找所有用户
User.find()
    .then(users => {
        console.log('All users:', users);
    })
    .catch(err => {
        console.error('Error finding users:', err);
    });

// 根据条件查找用户
User.findOne({ name: 'Alice' })
    .then(user => {
        console.log('User found:', user);
    })
    .catch(err => {
        console.error('Error finding user:', err);
    });

3. 更新文档

// 更新用户信息
User.findByIdAndUpdate('60c72b2f9b1d8e2f30b8b2f3', { age: 26 }, { new: true })
    .then(user => {
        console.log('User updated:', user);
    })
    .catch(err => {
        console.error('Error updating user:', err);
    });

4. 删除文档

// 删除用户
User.findByIdAndDelete('60c72b2f9b1d8e2f30b8b2f3')
    .then(user => {
        console.log('User deleted:', user);
    })
    .catch(err => {
        console.error('Error deleting user:', err);
    });

四、Schema 中的高级功能

1. 中间件(Middleware)

Mongoose 支持在文档保存、删除、更新等操作之前或之后执行中间件。

userSchema.pre('save', function(next) {
    console.log('A user is about to be saved:', this);
    next();
});

userSchema.post('save', function(doc, next) {
    console.log('A user has been saved:', doc);
    next();
});

2. 虚拟属性(Virtual Properties)

虚拟属性是不会存储在 MongoDB 中的属性,但可以像普通属性一样使用。

userSchema.virtual('fullInfo').get(function() {
    return `${this.name} (${this.age} years old)`;
});

const user = new User({ name: 'Alice', age: 25 });
console.log(user.fullInfo);  // 输出: Alice (25 years old)

3. 静态方法和实例方法

可以在 Schema 上定义静态方法和实例方法,以便在模型上调用。

// 静态方法
userSchema.statics.findByEmail = function(email) {
    return this.findOne({ email });
};

// 实例方法
userSchema.methods.isAdult = function() {
    return this.age >= 18;
};

const User = mongoose.model('User', userSchema);

// 使用静态方法
User.findByEmail('alice@example.com')
    .then(user => {
        console.log('User found by email:', user);
    });

// 使用实例方法
const user = new User({ name: 'Alice', age: 25 });
console.log(user.isAdult());  // 输出: true

五、错误处理和调试

在开发过程中,处理错误和调试是很重要的。

1. 捕获和处理错误

在异步操作中使用 try-catch.catch 来捕获和处理错误。

async function createUser() {
    try {
        const user = new User({ name: 'Bob', age: 30, email: 'bob@example.com' });
        const savedUser = await user.save();
        console.log('User saved:', savedUser);
    } catch (err) {
        console.error('Error saving user:', err);
    }
}

createUser();

2. 启用调试模式

Mongoose 提供了调试模式,可以帮助你查看底层的 MongoDB 操作。

mongoose.set('debug', true);

总结

Mongoose 是一个功能强大且灵活的 MongoDB ORM 工具,通过定义 Schema 和 Model,可以方便地进行 CRUD 操作,并且支持数据验证、钩子、中间件、虚拟属性等高级特性。通过上述示例,你可以快速上手并使用 Mongoose 进行数据库操作。根据具体需求,你还可以进一步扩展和优化代码。