MongoDB

参考:MongoDB 教程 | 菜鸟教程

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。

MongoDB是一个基于文档的 NoSQL 数据库,它使用类似 JSON 的文档模型存储数据,这使得数据存储变得非常灵活。

非关系数据库当中功能最丰富,最像关系数据库的。

文章目录

历史

MongoDB 最初是由 10gen 公司于 2007 年开发的,最初目标是打造一个平台即服务(PaaS)产品。

在开发过程中,他们意识到当时市场缺乏一个现代化、面向互联网应用的数据库,于是把精力从平台转向数据库,最终在 2009 年 开源了 MongoDB。

MongoDB 来自 "humongous" 的简写,意思是"庞大的",代表它面向大规模数据应用。

介绍

MongoDB 的设计理念是为了应对大数据量、高性能和灵活性需求,数据以类似 JSON 的文档形式存储:

BSON:Binary JSON 的缩写,是 MongoDB 用来存储和传输文档的二进制形式的 JSON。

使用

DDL
指定/创建/删除 数据库

(如果该数据库不存在,MongoDB将自动创建它。)

javascript 复制代码
> use DATABASE_NAME 
switched to db runoob
> db
runoob

db是显示当前数据库名称

默认是 test 数据库。

db.dropDatabase() 将删除当前正在使用的 myDatabase 数据库及其所有集合

查看所有数据库
javascript 复制代码
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
创建集合

db.createCollection("myNewCollection")

DML
插入文档

所有存储在集合中的数据都是 BSON 格式。

插入单个

db.collection.insertOne(document, options)

  • document:要插入的单个文档。【如果__id已存在,会更新】
  • options(可选):一个可选参数对象,可以包含 writeConcern 和 bypassDocumentValidation 等。
javascript 复制代码
db.myCollection.insertOne({
    name: "Alice",
    age: 25,
    city: "New York"
});

返回:
{
    "acknowledged": true,
    "insertedId": ObjectId("60c72b2f9b1d8b5a5f8e2b2d")
}
插入多个

db.collection.insertMany(documents, options)

  • documents:要插入的文档数组。
  • options(可选):一个可选参数对象,可以包含 ordered、writeConcern 和 bypassDocumentValidation 等。
javascript 复制代码
db.myCollection.insertMany([
    { name: "Bob", age: 30, city: "Los Angeles" },
    { name: "Charlie", age: 35, city: "Chicago" }
]);

返回结果:
{
    "acknowledged": true,
    "insertedIds": [
        ObjectId("60c72b2f9b1d8b5a5f8e2b2e"),
        ObjectId("60c72b2f9b1d8b5a5f8e2b2f")
    ]
}
查询 DQL

db.collection.find(query, projection)

  • query:用于查找文档的查询条件。默认为 {},即匹配所有文档。
  • projection(可选):指定返回结果中包含或排除的字段。

查找所有文档: db.myCollection.find(); (findOne() 只返回第一个。)

按条件查找:db.myCollection.find({ age: { $gt: 25 } });

按条件查找,并只返回指定字段:

shell 复制代码
db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);

后缀加 .pretty() 进行格式化:

js 复制代码
db.col.find().pretty()
{
        "_id" : ObjectId("56063f17ade2f21f36b03133"),
        "title" : "MongoDB 教程",
        "description" : "MongoDB 是一个 Nosql 数据库",
        "by" : "菜鸟教程",
        "url" : "http://www.runoob.com",
        "tags" : [
                "mongodb",
                "database",
                "NoSQL"
        ],
        "likes" : 100
}

使用比较操作符$gt、$lt、$gte、$lte、$eq、$ne

(很好懂,great than, ... , not equal等)

查找年龄大于 25 的文档: $gt

复制代码
db.myCollection.find({ age: { $gt: 25 } });

使用逻辑操作符$and、$or、$not、$nor

查找年龄大于 25 且城市为 "New York" 的文档: $and

js 复制代码
db.myCollection.find({
    $and: [
        { age: { $gt: 25 } },
        { city: "New York" }
    ]
});

使用正则表达式

查找名字以 "A" 开头的文档:

复制代码
db.myCollection.find({ name: /^A/ });

投影

只返回名字和年龄字段: 其实就是 , 后面的 {}

js 复制代码
db.myCollection.find(
    { age: { $gt: 25 } },
    { name: 1, age: 1, _id: 0 }
);

排序

按年龄降序排序: sort

复制代码
db.myCollection.find().sort({ age: -1 });

limit

js 复制代码
//返回前 10 个文档:
db.myCollection.find().limit(10);

//跳过前 5 个文档,返回接下来的 10 个文档:
db.myCollection.find().skip(5).limit(10);

查找年龄大于 25 且城市为 "New York" 的文档,只返回名字和年龄字段,按年龄降序排序,并返回前 10 个文档:

js 复制代码
db.myCollection.find(
    {
        $and: [
            { age: { $gt: 25 } },
            { city: "New York" }
        ]
    },
    { name: 1, age: 1, _id: 0 }
).sort({ age: -1 }).limit(10);

【索引】

MongoDB中使用 B+树 数据结构存储索引

如果文档中包含索引字段,就会插入 B+ 树索引中;如果缺少索引字段,MongoDB 会将缺失字段视为 null 插入索引 (是稀疏索引就不插入了,适合过滤)

索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

索引类型:

  • 单字段索引:基于单个字段的索引。
  • 复合索引:基于多个字段组合的索引。
  • 文本索引:用于支持全文搜索。
  • 地理空间索引:用于地理空间数据的查询。
  • 哈希索引:用于对字段值进行哈希处理的索引。
创建索引

db.<collection>.createIndex( keys, options )

options:

  • unique:如果设置为 true,则创建唯一索引,确保索引字段的值在集合中是唯一的。
  • background:如果设置为 true,则索引创建过程在后台运行,不影响其他数据库操作。
  • name:指定索引名称,如果不指定,MongoDB 会根据索引的字段自动生成一个名称。
  • sparse:如果设置为 true,创建稀疏索引,只索引那些包含索引字段的文档
  • expireAfterSeconds:设置索引字段的过期时间,MongoDB 将自动删除过期的文档。
  • v:索引版本,通常不需要手动设置。
  • weights:为文本索引指定权重。
javascript 复制代码
// 创建 age 字段的升序索引
db.myCollection.createIndex({ age: 1 });
// 降序
db.myCollection.createIndex({ age: -1 });
// 先按 age 降序,再按 name 升序排序 【对于经常一起使用的字段,考虑创建复合索引以提高查询效率。】
db.myCollection.createIndex({ age: -1, name: 1 });

// 创建 name 字段的文本索引 【文本索引只支持 "text" 类型,不支持使用 1 或 -1。】
db.myCollection.createIndex({ name: "text" });


// 创建唯一索引
db.collection.createIndex( { field: 1 }, { unique: true } )

// 创建后台运行的索引
db.collection.createIndex( { field: 1 }, { background: true } )

// 创建稀疏索引
db.collection.createIndex( { field: 1 }, { sparse: true } )

// 创建文本索引并指定权重
db.collection.createIndex( { field: "text" }, { weights: { field: 10 } } )
创建地理空间索引
对于存储地理位置数据的字段,可以使用 2dsphere 或 2d 索引类型来创建地理空间索引。

// 2dsphere 索引,适用于球形地理数据
db.collection.createIndex( { location: "2dsphere" } )

// 2d 索引,适用于平面地理数据
db.collection.createIndex( { location: "2d" } )

从 MongoDB 3.2 版本开始,可以使用哈希索引对字段进行哈希,以支持大范围的数值查找。

js 复制代码
db.collection.createIndex( { field: "hashed" } )

删除索引:

js 复制代码
// 删除指定的索引
db.collection.dropIndex( "indexName" )

// 删除所有索引
db.collection.dropIndexes()

聚合

MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。(有点类似 SQL 语句中的 count(*)。)

aggregate v. 合计

db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

js 复制代码
//对于下面数据聚合:
{
   _id: ObjectId(7df78ad8902c)
   title: 'MongoDB Overview', 
   description: 'MongoDB is no sql database',
   by_user: 'runoob.com',
   url: 'http://www.runoob.com',
   tags: ['mongodb', 'database', 'NoSQL'],
   likes: 100
},
{
   _id: ObjectId(7df78ad8902d)
   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
},
{
   _id: ObjectId(7df78ad8902e)
   title: 'Neo4j Overview', 
   description: 'Neo4j is no sql database',
   by_user: 'Neo4j',
   url: 'http://www.neo4j.com',
   tags: ['neo4j', 'database', 'NoSQL'],
   likes: 750
},


//shell
> db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
// 类似mysql分组操作: select by_user, count(*) from mycol group by by_user

//返回:
{
   "result" : [
      {
         "_id" : "runoob.com",
         "num_tutorial" : 2
      },
      {
         "_id" : "Neo4j",
         "num_tutorial" : 1
      }
   ],
   "ok" : 1
}
>

{$sum : 1} 为计数,每个条目+1

{ sum: "amount" } 加字段的是对对应字段求和

与 MySQL 相比较

MongoDB 动态模式,可任意字段

嵌套数组

这正好是我的项目选择 MongoDB 的原因。

我想维护 面试记录 ,而面试记录又要存 多组"题目-回答"

这个时候使用 mysql 就需要另外维护一个 题目-回答 表,并且每次查询要联表,性能就差点。

如下JSON的 qaList 字段:

js 复制代码
{
  "_id": "session_abc123",
  "userId": "user_001",
  "username": "张三",
  "startTime": "2025-05-17T10:30:00",
  "endTime": "2025-05-17T10:35:00",
  "qaList": [
    {
      "question": "什么是TCP三次握手?",
      "answer": "SYN -> SYN+ACK -> ACK,建立连接...",
      "tags": ["计网", "TCP", "握手"]
    },
    {
      "question": "C++中虚函数如何实现?",
      "answer": "依靠虚表指针(vptr)...",
      "tags": ["C++", "面向对象"]
    }
  ],
  "evaluation": "整体表现良好,回答流畅,专业术语掌握较好。",
  "score": "85/100",
  "status": "finished"
}

没有外键约束

MongoDB 设计之初就强调高性能、灵活性和水平扩展性,因此牺牲了像外键这种跨集合一致性约束。所以它不会自动校验引用的文档是否存在,无法做到像 MySQL 中的"级联删除"、"级联更新"。

使用 $lookup 可以做联表查询

相关推荐
Channing Lewis2 小时前
SQL Server 简介和与其它数据库对比
数据库
阿文弟3 小时前
浅谈Mysql的MVCC机制(RC与RR隔离级别)
数据库·mysql
要睡觉_ysj3 小时前
MySQL锁机制与MVCC深度解析
数据库·mysql
看到千里之外的云4 小时前
用service 和 SCAN实现sqlplus/jdbc连接Oracle 11g RAC时负载均衡
数据库·oracle·负载均衡
野犬寒鸦4 小时前
Redis核心数据结构操作指南:字符串、哈希、列表详解
数据结构·数据库·redis·后端·缓存·哈希算法
无心水5 小时前
【后端高阶面经:MongoDB篇】41、MongoDB 是怎么做到高可用的?
java·开发语言·mongodb·java面试·高可用·后端高阶面经·后端工程师的高阶面经
袖清暮雨5 小时前
ClickHouse讲解
大数据·数据库·数据仓库·clickhouse·oracle
vvilkim5 小时前
MongoDB 备份与恢复策略全面指南:保障数据安全的完整方案
数据库·mongodb
无心水5 小时前
【后端高阶面经:MongoDB篇】40、怎么优化MongoDB的查询性能?
java·开发语言·mongodb·java面试·后端高阶面经·后端工程师的高阶面经·java高阶面经
是桃萌萌鸭~5 小时前
使用 mysqldump 获取 MySQL 表的完整创建 DDL
数据库·mysql