MongoDB的常用语法

DATABASE MONGODB

Posted by gomyck on August 25, 2022

快速入门指南

如何安装

采用docker 安装 MongoDB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: '3.1'
services:
  mongo:
    image: mongo
    restart: unless-stopped
    environment:
      TZ: Asia/Shanghai
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: root
    ports:
      - 27017:27017
    logging:
      driver: json-file
      options:
        max-size: "300M"
        max-file: "3"
  mongo-express:
    image: mongo-express
    restart: unless-stopped
    ports:
      - 8081:8081
    logging:
      driver: json-file
      options:
        max-size: "300M"
        max-file: "3"
    environment:
      TZ: Asia/Shanghai
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: root
      ME_CONFIG_MONGODB_URL: mongodb://root:root@mongo:27017/

如何连接

使用 navicat 或者 docker 安装的 mongo-express 来连接

mongodb://[username:password@]host1[:port1][,host2[:port2],…[,hostN[:portN]]][/[database][?options]]

快速入门指南

RDBMS & MongoDB

RDBMS MONGO 对应关系
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持 内嵌文档
primary key primary key 主键,MongoDB自动将_id字段设置为主键

以上为关系型数据库与 MongoDB 的对比关系(数据结构维度)

数据库操作

MongoDB 的操作维度都是现切换到对应的工作空间(use 数据库), 然后在使用对应的命令对当前工作空间做操作

1
2
3
4
5
6
7
8
9
-- 1. 查看所有数据库
show dbs;

-- 2. 创建/切换数据库
use database;

-- 3. 删除数据库
db.dropDatabase()

集合新增相关操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 1. 新建集合
db.createCollection(name,  { capped: true, autoIndexId: true, size: 6142800, max: 10000 } )
-- capped: 布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
-- autoIndexId: 布尔 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。
-- size: 数值 (可选)为固定集合指定一个最大值,即字节数。如果 capped 为 true,也需要指定该字段。
-- max: 数值 (可选)指定固定集合中包含文档的最大数量。

-- 2. 向数据库对应的集合新增数据(集合不存在则新建)
db.[tablename].insert({"key": "value"})
db.[tablename].insertOne({"key": "value"})
db.[tablename].insertMany([{"key1": "value1"}, {"key2": "value2"}])
-- insert 与 insertOne的区别在于  后者返回插入后的 ID 以及 ack 标志

集合修改文档操作

语法:

1
2
3
4
5
6
7
8
9
db.collection.update(
   <query>,   update的查询条件,类似sql update查询内where后面的。
   <update>,  update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
   {
     upsert: <false>,         可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
     multi: <false>,          可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
     writeConcern: <document>   可选,抛出异常的级别。
   }
)
1
2
3
4
-- 1. 更新 demo2 集合, 查找 kkk=0 的项, 修改 aaa 列为 232, 如果没有 aaa 列, 就新增, 该操作是批量操作({"multi": true})
db.demo2.update({"kkk":0}, {$set: {"aaa": 232}}, {"multi": true})
-- 等效于
db.demo2.update({"kkk":0}, {$set: {"aaa": 232}}, false, true)

集合删除文档操作

语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
db.collection.remove(
   <query>,                     (可选)删除的文档的条件。
   {
     justOne: <boolean>,        (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
     writeConcern: <document>   (可选)抛出异常的级别。
   }
)

db.collection.deleteOne(
    <query>
)

db.collection.deleteMany(
    <query>
)
1
2
3
4
-- 1. 删除 demo2 集合 kkk=0 的数据集, 只删除匹配的第一条
db.demo2.remove({"kkk":0}, true)
-- 等效于
db.demo2.deleteOne({"kkk":0})

集合查询文档操作

通过上述片段, 我们可以发现一些规律: MongoDB 入参, 都是 json 类型数据, 动作&条件 等使用 $.. 这些关键字来代替, 比如: $set

下面通过查询的例子, 更加可以看到其中的规律

语法:

1
2
3
4
db.collection.find(
    <query>,
    <projection>  可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
)[.pretty()]
1
2
3
4
5
6
7
8
9
10
-- 1. 查询 demo2 中 aaa=232, kkk 大于或等于0, 并且 kkk 等于 0 或 2, 并且只过滤出 aaa 列存储的类型是 doubule 的数据
-- limit(2): 只查 2 条
-- skip(1): 略过前 1 条数据
-- .sort({"kkk":1}): 按照 aaa 字段升序排列   (-1 是降序)
db.demo2.find({
    "aaa": 232,
    "aaa": {$type: 'double'},
    $or: [{"kkk": 0}, {"kkk": 2}],
    "kkk": {$gte: 0}
}).skip(1).limit(2).sort({"aaa":1}).pretty()

find函数接收的查询数组, 都是 and 操作, 如果想加入 or, 那么就加一个 or 的属性, 支持比较运算符

集合索引操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 1. demo2创建索引, 用 kkk 列  (升序)   -1 是降序
db.demo2.createIndex({"kkk":1}, {"name": "idx_kkk", "unique": false})

-- 2. 查看所有索引
db.demo2.getIndexes()

-- 3. 查看索引大小
db.demo2.totalIndexSize()

-- 4. 删除所有索引
db.demo2.dropIndexes()

-- 5. 删除指定索引
db.col.dropIndex("idx_kkk")

集合聚合操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
db.demo2.aggregate([
    {
        $group: {
            _id: "$kkk",
            xxx: {$sum:   "$aaa"},
            ccc: {$avg:   "$aaa"},
                    zzz: {$min:   "$aaa"},
                    vvv: {$max:   "$aaa"},
                    bbb: {$push:  "$aaa"},
                    ttt: {$first: "$aaa"},
                    qqq: {$last:  "$aaa"},
                    rrr: {$addToSet: "$aaa"},
        }
    },
    {
        $project: {
            _id: 1,
            xxx: 1
        }
    }
])

最终输出的结果只有 _id 和 xxx, 因为被 project 管道过滤了

MongoDB 集合函数接收为管道函数, 支持经过的管道如下:

1
2
3
4
5
6
7
8
9
10
11
$project : 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match   : 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit   : 用来限制MongoDB聚合管道返回的文档数。
$skip    : 在聚合管道中跳过指定数量的文档,并返回余下的文档。
$unwind  : 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group   : 将集合中的文档分组,可用于统计结果。
$sort    : 将输入文档排序后输出。
$geoNear : 输出接近某一地理位置的有序文档。
$out	 : 把管道的结果写入某个集合。
$redact	 : 控制特定数据的访问。
$lookup  : 多表关联

$lookup 管道函数示例:

1
2
3
4
5
6
7
8
9
10
11
db.产品.aggregate([
   {
     $lookup:
       {
         from: "库存",
         localField: "产品item",
         foreignField: "库存sku",
         as: "inventory_docs"
       }
  }
])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    "_id" : NumberInt("1"),
    "item" : "almonds",
    "price" : NumberInt("12"),
    "quantity" : NumberInt("2"),
    "inventory_docs" : [
        {
            "_id" : NumberInt("1"),
            "sku" : "almonds",
            "description" : "product 1",
            "instock" : NumberInt("120")
        }
    ]
}