MongoDB 5.x安装使用, aggregation管道与sql语法参照
1. 安装
使用 docker-compose
参考: https://hub.docker.com/_/mongo
version: '3.1'
services:
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: example
ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/
2. 基本使用
- 切换数据库
show dbs # 查看数据库
show collections # 查看集合
use test # 切换数据库, 没有的话,在创建集合时,会自动创建
- 创建集合
db.createCollection('t_user')
- 添加数据
# 单条插入
db.t_user.insert(
{ "name": "hello", "age": 22, "sex": "男" }
)
# 批量插入
db.t_user.insertMany([
{ "name": "hello1", "age": 23, "sex": "男" },
{ "name": "hello2", "age": 24, "sex": "男" },
{ "name": "hello3", "age": 25, "sex": "男" }
])
3. 管道查询 aggregation
Sql语法中
- 基本查询where:
<>=!
/and
/or
/in
/not in
/like
- 关联查询join:
left join
/right join
/inner join
- 字段排序order:
asc
/desc
在MongoDB 5.x的管道中都可以实现类似的功能
3.1 基本运算
参照表:
SQL where |
MongoDB $match |
---|---|
= | $eq |
!= | $ne |
> | $gt |
>= | $gte |
< | $lt |
<= | $lte |
sql
select * from t_user where age=23;
mongo
db.t_user.aggregate([{
$match: {
$expr: {
$eq: ["$age", 23]
}
}
}])
或者
db.t_user.aggregate([{
$match: {
age: { $eq: 23 }
}
}])
3.2 模糊查询 like
在mongo中使用$regex
正则
sql
select * from t_user where name like '%hello%';
mongo
db.t_user.aggregate([{
$match: {
name: {
$regex: "hello",
$options:'i'
}
}
}])
3.3 列表查询 in
在mongo中使用$in
sql
select * from t_user where name in ('hello', 'hello1');
mongo
db.t_user.aggregate([{
$match: {
name: {
$in: ["hello", "hello1"]
}
}
}])
3.4 逻辑取反 $not
在mongo中使用$not
对查询逻辑进行取反. 比如配合$in
实现not in
的效果, 也可以使用$nin
sql
select * from t_user where name not in ('hello', 'hello1');
mongo
db.t_user.aggregate([{
$match: {
name: {
$not: { $in: ["hello", "hello1"] }
}
}
}])
3.5 条件and
在mongo中使用$and
sql
select * from t_user where name='hello' and age=23;
mongo
# 方式1
db.t_user.aggregate([{
$match: {
name: { $eq: "hello" },
age: { $eq: 23 }
}
}])
# 方式2
db.t_user.aggregate([{
$match: {
$and: [
{name: { $eq: "hello" }},
{age: { $eq: 23 }}
]
}
}])
3.6 条件or
在mongo中使用$or
sql
select * from t_user where name='hello' or age=24;
mongo
db.t_user.aggregate([{
$match: {
$or: [
{name: { $eq: "hello" }},
{age: { $eq: 24 }}
]
}
}])
3.7 条件and和or嵌套使用
sql
select * from t_user where name='hello' and (age=23 or sex='男');
mongo
db.t_user.aggregate([{
$match: {
$and: [
{name: { $eq: "hello" }},
{$or:[
{age: { $eq: 23 }},
{sex: { $eq: "男" }}
]}
]
}
}])
3.8 分组group
在mongo中使用$group
, 分组字段使用_id
,形式:
_id: {name: "$name", age: "$age"}
SQL | mongo |
---|---|
count | $count |
sum | $sum |
max | $max |
min | $min |
avg | $avg |
sql
select count(*) as count, sum(age) as ageSum, max(age) as ageMax, min(age) as ageMin, avg(age) as ageAvg from t_user group by name;
mongo
db.t_user.aggregate([{
$group: {
_id: {name: "$name"},
count: {$count: {}},
ageSum: {$sum: "$age"},
ageMax: {$max: "$age"},
ageMin: {$min: "$age"},
ageAvg: {$avg: "$age"}
}
}])
3.9 排序sort
在mongo中使用$sort
- 1 正序 asc
- -1 倒序 desc
sql
select * from t_user order by name asc, age desc;
mongo
db.t_user.aggregate([{
$sort : { name: 1, age : -1}
}])
3.10 表链接 join
在mongo中使用$lookup
, 在mongo中只存在左连接类似left join
功能, 如果想使用right join
就只能调换两个集合的顺序;
结合$unwind
指令, 通过preserveNullAndEmptyArrays
属性实现inner join
的效果.
语法示例说明:
$lookup: {
from: 't_info', # 被连接的集合
let: {info_name: "$name"}, # 连接字段需要先指定引用变量的名称,才能在管道中被使用
pipeline: [{ # 通过管道实现连接功能
$match: { # 通过$match 实现连接条on的功能
$expr: {
$and: [ ## 通过 $$ 引用let定义的变量
{ $eq: [ "$$info_name", "$name" ] }
]
}
}
}],
as: 't_info' # 指定被连接的文档在管道中的名字
}
创建t_info
集合
db.createCollection('t_info')
db.t_info.insertMany([
{ "name": "hello", "age": 23, "addr": "银河" }
])
sql
select * from t_user u left join t_info t on u.name=t.name;
mongo
db.t_user.aggregate([{
$lookup: {
from: 't_info',
let: {info_name: "$name"},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: [ "$$info_name", "$name" ] }
]
}
}
}],
as: 't_info'
}}
,{$unwind:{ path: '$t_info', preserveNullAndEmptyArrays: true }}
,{$project: {name:1, age:1, addr:"$t_info.addr"}}
])
preserveNullAndEmptyArrays: false (默认) inner join