Node操作MongoDB

314 阅读2分钟

原生MongoDB

首先需要下载mongodb包npm i mongodb -S

连接数据库

// 客户端
const MongoClient = require('mongodb').MongoClient;
// 连接URL
const url = 'mongodb://localhost:27017';
// 数据库名
const dbName = 'test';
// 创建客户端
const client = new MongoClient(url,{useNewUrlParser: true}); 
// 2.获取数据库
const db = client.db('dbName');
// 3.获取集合(表)
const fruits = db.collection('fruits');

插入数据

fruits.insertOne({name: `水果${i+1}`, price: i*5})

await books.insertMany([
      {
        title: 'MongoDB Overview', 
        description: 'MongoDB is no sql database',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 100
     },
     {
        title: 'NoSQL Overview', 
        description: 'No sql database is very fast',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 10
     },
     {
        title: 'Neo4j Overview', 
        description: 'Neo4j is no sql database',
        by_user: 'Neo4j',
        url: 'http://www.neo4j.com',
        tags: ['neo4j', 'database', 'NoSQL'],
        likes: 750
     }
    ])

删除数据

await fruits.deleteOne({price: 50})

await fruits.deleteMany();

更改数据

await fruits.updateOne({name: '水果2'}, {$set: {name: '水果一'}});

查询数据

查询所有

await fruits.find().toArray();

选定返回字段

db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
// SELECT _id, item, status from inventory WHERE status = "A"

条件查询

await fruits.find({name: '水果3', price: 20}).toArray();

OR AND 运算符

// AND find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件
r = await fruits.find({name: '水果3', price: 20}).toArray(); 

// OR
r = await fruits.find({
  $or: [
	{name: '水果3'},
	{name: '水果4'}
  ]
}).toArray()

// OR和AND结合r = await fruits.find({price: {$lte : 30}, $or: [{name: '水果3'},{name: '水果4'},{name: '水果9'}]}).toArray()

模糊查询(正则)

// 模糊查询 使用正则表达式进行模糊查询
r = await fruits.find({name: /水果/}).toArray();
r = await fruits.find({name: /^水/}).toArray();
r = await fruits.find({name: /3$/}).toArray();

条件运算符

/**
 * 条件操作符
 * $gt >
 * $lt <
 * $gte >=
 * $lt <=  
 */
r = await fruits.find({price: {$gt : 40}}).toArray()
r = await fruits.find({price: {$gt: 20, $lt: 40}}).toArray()

分页查询

    /**
     * 分页查询
     * limit() 读取指定数量的数据记录
     * skip() 跳过指定数量的数据(偏移量)
     */
    r = await fruits.find().skip(3).limit(5).toArray();

排序

    /**     * 排序     * sort()方法 1升序 -1降序     */    r = await fruits.find().sort({price: -1}).toArray();

聚合

/**
 * 聚合函数
 * $sum 计算总数
 * $avg 计算平均值
 * $min 计算最小值
 * $max 计算最大值
 */
const books = db.collection('books');
    await books.insertMany([
      {
        title: 'MongoDB Overview',
        description: 'MongoDB is no sql database',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 100
      },
      {
        title: 'NoSQL Overview',
        description: 'No sql database is very fast',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 10
      },
      {
        title: 'Neo4j Overview',
        description: 'Neo4j is no sql database',
        by_user: 'Neo4j',
        url: 'http://www.neo4j.com',
        tags: ['neo4j', 'database', 'NoSQL'],
        likes: 750
      }
    ])
	// select by_user as _id, count(*) as num_tutorial from books group by by_user
    r = await books.aggregate([
      {
        $group: {
          _id: '$by_user',
          num_tutorial: { $sum: 1 }
        }
      }
    ]).toArray();

    // select by_user as _id, count('likes') as num_tutorial from books group by by_user
    r = await books.aggregate([
      {
        $group: {
          _id: '$by_user',
          num_tutorial: { $sum: '$likes' }
        }
      }
    ]).toArray();

联合查询($lookup)

    /**
     * 联合查询
     * $lookup 左连接
     */
    const orders = await db.collection('orders');
    await orders.insertOne({_id: 1, product_id: 154, status: 1});
    const products = await db.collection('products');
    await products.insertMany([
      { _id: 154, name: '笔记本电脑' },
      { _id: 155, name: '耳机' },
      { _id: 156, name: '台式电脑' }
    ])
    r = await orders.aggregate([
      {
        $lookup: {
          from: 'products', // 右集合
          localField: 'product_id', // 左集合join字段
          foreignField: '_id', // 右集合join字段
          as: 'orderdetails' // 新生成字段(类型array)
        }
      }
    ]).toArray();
    console.log('查询所有数据: ', JSON.stringify(r));

ORM Mongoose

下载mongoose包npm i mongoose -S

连接数据库

const mongoose = require('mongoose')

// 1. 连接
mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
const conn = mongoose.connection;

conn.on('error', () => console.error('连接数据库失败'));

定义Schema(Table)

conn.once('open', async () => {  // 2. 定义一个Schema - Table  const Schema = mongoose.Schema({    category: String,    name: String  });
})

创建数据模型

const Model = mongoose.model('fruit', Schema);

新增数据

// 4. 创建,create返回Promise
let r;
r = await Model.create({
  category: '温带水果',
  name: '苹果',
  price: 5
});
console.log('插入数据: ', r);

更改数据

    // 6. 更新 updateOne 返回Query
    r = await Model.updateMany({name: '苹果'}, {$set: {name: '芒果'}});
    console.log('修改成功: ', r);

删除数据

    // 7. 删除 deleteOne返回Query
    r = await Model.deleteMany({name: '芒果'});

查询数据

    // 5. 查询数据 find返回Query,它实现then和catch,可以当Promise使用
    // 如果需要返回Promise,调用exec()
    r = await Model.find();
    console.log('查询数据:', r);

定义字段 Schema

  const blogSchema = mongoose.Schema({
    title: { type: String, required: [true, '标题为必填项'] }, // 定义校验规则
    author: String,
    body: String,
    comments: [{ body: String, date: Date }], // 定义对象数组
    date: { type: Date, default: Date.now }, // 指定默认值
    hidden: Boolean,
    meta: {
      // 定义对象
      votes: Number,
      favs: Number
    }
  });

定义多个索引

  // 定义多个索引  blogSchema.index({title: 1, author: 1, date: -1});  const blogModel = mongoose.model('blog', blogSchema);  const blog = new blogModel({    title: 'nodejs持久化',    author: 'jerry',    body: '这是关于Node.js博客'  })  r = await blog.save();  console.log('新增blog ', r)

定义实例方法

抽象出常用方法便于复用

  // 定义实例方法
  blogSchema.methods.findByAuthor = function(auth) {
    return this.model('blog').find({author: this.author}).exec();
  }
  // 获取模型实例
  const BlogModel = mongoose.model('blog', blogSchema);
  const blog = new BlogModel({
    title: 'nodejs持久化',
    author: 'jerry',
    body: '这是关于Node.js博客'
  });
  // 调用方法
  r = await blog.findByAuthor();
  console.log('findAuthor', r);

静态方法

  // 静态方法
  blogSchema.statics.findByAuthor = function(author){
    return this.model('blog').find({author}).exec();
  }
  // 获取模型实例
  const BlogModel = mongoose.model('blog', blogSchema);
  r = await BlogModel.findByAuthor('jerry');
  console.log('findByAuthor: ', r)

虚拟属性

  // 虚拟属性  blogSchema.virtual('commentsCount').get(function() {    return this.comments.length;  })  // 获取模型实例  const blog = mongoose.model('blog', blogSchema);  r = await blog.findOne({author: 'jerry'});  console.log('blog留言数: ', r.commentsCount);