cxl
Published on 2025-05-16 / 14 Visits
0
0

MongoDB之SQL

MongoDB 作为 NoSQL 数据库,采用文档存储而非关系型表格结构,但其核心操作与 SQL 有诸多相似之处。本文将详细介绍 MongoDB 的各类操作,特别是强大的聚合功能。这里跟上一篇一样,使用命令行进行操作,也需要单独下载mongosh工具,或者使用可视化客户端连接。

1. 数据库与集合操作

1.1 数据库管理

  // 创建或切换数据库(MongoDB 按需创建)
  use mydb   # 相当于SQL中的  CREATE DATABASE mydb 和 USE mydb;;
  
  // 查看当前数据库
  db.getName()      # 相当于SQL中的 select database();
  
  // 删除当前数据库
  db.dropDatabase()  # 相当于SQL中的 DROP DATABASE mydb;
  
  // 查看所有数据库
  show dbs   # 相当于SQL中的  SHOW DATABASES;
  

1.2 集合管理

  // 创建集合(MongoDB 按需创建)
  db.createCollection("users")   # 相当于SQL中的  CREATE TABLE users(id INT, name VARCHAR(50) ...)
  
  // 创建带选项的集合(如固定大小)
  db.createCollection("logs", { capped: true, size: 10485760 })  # size单位字节,10485760为10MB,其它高级用法如验证文档格式可通过 db.createCollection.help()  获取文档地址查看
  
  // 查看所有集合
  show collections  # 相当于SQL中的 SHOW TABLES;
  
  // 删除集合
  db.users.drop()  # 相当于SQL中的 DROP TABLE users;

2. 文档操作(增删改查)

2.1 插入文档

  // 插入单条文档,相当于SQL中的:INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30);
  db.users.insertOne({
    _id: 1,
    name: "Alice",
    age: 30,
    hobbies: ["reading", "swimming"]
  })
  
  // 插入多条文档,相当于SQL中的:INSERT INTO users (id, name, age) VALUES (2, 'Bob', 25), (3, 'Charlie', 35);
  db.users.insertMany([
    { _id: 2, name: "Bob", age: 25 },
    { _id: 3, name: "Charlie", age: 35 }
  ])
  

2.2 查询文档

  // 查询所有文档,相当于SQL的:SELECT * FROM users;
  db.users.find()
  
  // 条件查询(等于),相当于SQL的:SELECT * FROM users WHERE name = 'Alice';
  db.users.find({ name: "Alice" })
  
  // 条件查询(大于),相当于SQL的:SELECT * FROM users WHERE age > 30;
  db.users.find({ age: { $gt: 30 } })
  
  // 逻辑查询(AND),相当于SQL的:SELECT * FROM users WHERE age > 25 AND name != 'Charlie';
  db.users.find({ age: { $gt: 25 }, name: { $ne: "Charlie" } })
  
  // 逻辑查询(OR),相当于SQL的:SELECT * FROM users WHERE age < 30 OR name = 'Alice';
  db.users.find({ $or: [{ age: { $lt: 30 } }, { name: "Alice" }] })
  
  // 投影(仅返回指定字段),相当于SQL的:SELECT name, age FROM users WHERE name = 'Alice';
  db.users.find({ name: "Alice" }, { name: 1, age: 1, _id: 0 })

2.3 更新文档

  // 更新单条文档,相当于SQL的:UPDATE users SET age = 31 WHERE name = 'Alice';
  db.users.updateOne(
    { name: "Alice" },
    { $set: { age: 31 }, $addToSet: { hobbies: "running" } }
  )
  
  // 更新多条文档,相当于SQL的:UPDATE users SET age = age + 1 WHERE age >= 30;
  db.users.updateMany(
    { age: { $gte: 30 } },
    { $inc: { age: 1 } }
  )
  
  // 替换文档,相当于SQL的: REPLACE INTO users (id, name, age, job) VALUES (2, 'Robert', 26, 'Engineer');
  db.users.replaceOne(
    { name: "Bob" },
    { name: "Robert", age: 26, job: "Engineer" }
  )

2.4 删除文档

  // 删除单条文档,相当于SQL的:DELETE FROM users WHERE name = 'Charlie';
  db.users.deleteOne({ name: "Charlie" })
  
  // 删除多条文档,相当于SQL的:DELETE FROM users WHERE age < 30;
  db.users.deleteMany({ age: { $lt: 30 } })
  
  // 删除所有文档(保留集合),相当于SQL的:DELETE FROM users;
  db.users.deleteMany({})

3. 索引操作

3.1 创建索引

  // 创建单字段索引
  db.users.createIndex({ name: 1 })  // 1 表示升序,-1 表示降序
  
  // 创建复合索引
  db.users.createIndex({ age: 1, name: -1 })
  
  // 创建唯一索引
  db.users.createIndex({ email: 1 }, { unique: true })
  
  // 创建文本索引(用于全文搜索)
  db.users.createIndex({ bio: "text" })

3.2 查看和删除索引

  // 查看集合所有索引
  db.users.getIndexes()
  
  // 删除索引
  db.users.dropIndex("name_1")  // 索引名格式:字段名_排序方向

4. 聚合框架

MongoDB 聚合框架通过管道(pipeline)操作实现复杂的数据处理,功能远超 SQL 的 GROUP BY

4.1 常用聚合操作符

  • $match:筛选文档,类似 SQL 的 WHERE

  • $group:分组,类似 SQL 的 GROUP BY

  • $project:投影,类似 SQL 的 SELECT

  • $sort:排序,类似 SQL 的 ORDER BY

  • $limit:限制结果数量,类似 SQL 的 LIMIT

  • $skip:跳过文档,类似 SQL 的 OFFSET

  • $lookup:关联查询,类似 SQL 的 JOIN

4.2 聚合示例

示例 1:统计各年龄段人数

  # 相当于SQL的:SELECT age, COUNT(*) as count FROM users GROUP BY age ORDER BY count DESC;
  db.users.aggregate([
    { $group: { _id: "$age", count: { $sum: 1 } } },
    { $sort: { count: -1 } }
  ])

示例 2:计算平均年龄

  # 相当于SQL的:SELECT AVG(age) as averageAge FROM users;
  db.users.aggregate([
    { $group: { _id: null, averageAge: { $avg: "$age" } } }
  ])

示例 3:多表关联查询

  # 假设有 orders 集合,结构:{ userId: 1, amount: 100 }
  # 相当于SQL:
  #  SELECT u.name as userName, o.amount
  #      FROM orders o
  #      JOIN users u 
  #      ON o.userId = u.id;

  db.orders.aggregate([
    {
      $lookup: {
        from: "users",
        localField: "userId",
        foreignField: "_id",
        as: "userInfo"
      }
    },
    { $unwind: "$userInfo" },  // 展开数组
    { $project: { _id: 0, userName: "$userInfo.name", amount: 1 } }
  ])

示例 4:复杂聚合(统计每个用户的订单总数和总金额)

  # 相当于SQL:
  #  SELECT 
  #    u.name as userName,
  #    COUNT(o.id) as totalOrders,
  #    SUM(o.amount) as totalAmount
  #  FROM orders o
  #  JOIN users u ON o.userId = u.id
  #  GROUP BY u.id, u.name
  #  ORDER BY totalAmount DESC;  

  db.orders.aggregate([
    { $group: {
      _id: "$userId",
      totalOrders: { $sum: 1 },
      totalAmount: { $sum: "$amount" }
    }},
    { $lookup: {
      from: "users",
      localField: "_id",
      foreignField: "_id",
      as: "user"
    }},
    { $unwind: "$user" },
    { $project: {
      _id: 0,
      userName: "$user.name",
      totalOrders: 1,
      totalAmount: 1
    }},
    { $sort: { totalAmount: -1 } }
  ])

5. 高级聚合操作

5.1 数组操作

  // 假设有 products 集合:{ name: "phone", tags: ["electronics", "mobile"] }
  db.products.aggregate([
    { $unwind: "$tags" },  // 展开数组
    { $group: { _id: "$tags", count: { $sum: 1 } } },  // 统计标签出现次数
    { $sort: { count: -1 } }
  ])

5.2 窗口函数(MongoDB 5.0+)

  // 计算每个用户的订单金额排名
  db.orders.aggregate([
    { $sort: { amount: -1 } },
    {
      $setWindowFields: {
        partitionBy: null,
        sortBy: { amount: -1 },
        output: { rank: { $rank: {} } }
      }
    }
  ])

5.3 地理空间聚合

  // 假设有 stores 集合:{ name: "Store A", location: { type: "Point", coordinates: [longitude, latitude] } }
  db.stores.aggregate([
    {
      $geoNear: {
        near: { type: "Point", coordinates: [114.06667, 22.61667] },  // 深圳市中心
        distanceField: "distance",
        maxDistance: 10000,  // 单位米,即10公里内
        spherical: true
      }
    },
    { $limit: 5 }  // 返回最近的5个商店
  ])
  

6. 执行计划与优化

6.1 查看聚合执行计划

  db.users.explain("executionStats").aggregate([
    { $match: { age: { $gt: 25 } } },
    { $group: { _id: "$city", avgAge: { $avg: "$age" } } }
  ])

6.2 优化建议

  1. 尽早过滤数据:在管道开头使用 $match 减少数据量

  2. 合理使用索引:为 $match$sort 字段创建索引

  3. 避免大数据集排序$sort 操作会将数据加载到内存,可能导致内存溢出

  4. 使用 $indexStats 分析索引使用情况

      db.users.aggregate([{ $indexStats: {} }])

7. 帮助命令

‌7.1 数据库级帮助

  db.help() // 显示数据库操作命令列表 
  db.stats() // 查看当前数据库统计信息(含存储细节)

‌7.2 集合级帮助

  db.collection.help() // 列出指定集合支持的操作方法 
  db.collection.stats() // 查看集合存储统计 
  db.collection.getIndexes() // 查看集合索引配置

7‌.3 方法级帮助

  db.createCollection.help() // 查看创建集合方法的参数说明 
  db.collection.insert.help() // 查看插入操作的语法规范

总结

MongoDB 的操作虽然语法与 SQL 不同,但核心功能高度相似。聚合框架提供了比 SQL 更强大、灵活的数据处理能力,尤其适合复杂数据分析场景。掌握 MongoDB 的操作和聚合框架,能让你更高效地管理和分析非结构化数据。


Comment