mongdb数据库和关系型数据库完全不同, 主要在数据结构存储和查询语法方面。mongdb是把数据存在文档里面,文档里面是一种bson格式的数据(类似json格式),再通过mongdb的javascript语法取读取符合条件的文档内容用表的形式展示给我们。查询语句为 db.表名.find(query, projection);
含义如下
db是全局变量,固定不变
find 类似select关键字。 除了find,还有insert、update等等
query 类似where关键词后面的条件(可无,如有,需要用{}括起来)
projection 你要查询哪几个字段(可无,如有,需要用{}括起来)
关于变量query里面的字段名称,如果是多层嵌套的josn数组结构,需指定层级,示例如下
# 只有一层的josn结构
{
"name":"zhangsan",
"age":23
}
#查询name=zhangsan 的数据
db.t_user.find({"name":"zhangsan"});
# 多层嵌套的json数组结构
{
"name":"zhangsan",
"age":23,
"data": [{
"level":"1",
"level_no":"axcds"
}]
}
# 查询level_no=axcds
db.t_user.find({"data.level_no":"zhangsan"}); # 目标字段有多少层就按层依次用点隔开
就是
下面写了一些比较常用的查询语法
查询操作 | mongdb SQL | 关系型SQL | 备注 |
---|---|---|---|
全部数据全部字段 | db.t_user.find(); | select * from t_user; | |
查name=zhangsan | db.t_user.find({“name”:“zhangsan”}); | select * from t_user where name = “zhangsan”; | 字段名大小写敏感,name和Name不是同一个字段了;若多个and条件,{}里面逗号间隔即可 |
查name!=zhangsan | db.t_user.find({“name”:{$ne:“zhangsan”}}) | select * from t_user where name != “zhangsan”; | |
查name=null | db.t_user.find({“name”:null}) | select * from t_user where name is null | 不存在name字段的记录默认null,此时满足条件也会被查询出来 |
只查name和age字段 | db.t_user.find({“name”:“zhangsan”}, {name:1,age:1}); | select name, age from t_user where name = “zhangsan”; | 没有任何where条件时,前面的{}里面空着就行;后面那个{},省略就是默认查全部字段,不省略就是自定义查哪些字段。字段名称后的数字表示该字段 1展示 或 0不展示。 也可以使用true/false代替1/0 |
查询 in | db.t_user.find({“name”:{$in:[“zhangsan”,“lisi”]}}); | select * from t_user where name in (“zhangsan”,“lisi”); | in表示满足任意一个,nin表示均不满足=not in,all表示均满足 |
查询 not in | db.t_user.find({name:{$nin:[“zhangsan”,“lisi”]}}); | select * from t_user where name not in (“zhangsan”,“lisi”); | |
查询 or | db.t_user.find({“$or”:[{“name”:“zhangsan”},{“age”:18}]}); | select * from t_user where name = “zhangsan” or age = 18; | |
查询 范围 | db.t_user .find({“age”:{$ gte:18,$ lte:22}}) | select * from t_user where age >= 18 and age <= 22; | $lt $ge $lte $gte 代表 <、>、<=、>= |
模糊查询 | db.t_user .find({“name”: {“$regex”: /zhangsan/}}); | select * from t_user where name like ‘%zhangsan%’; | 都是正则表达式,类似的还有: 以zhang开头 /^zhang/ 等价 ‘zhang%’ 、 以zhang结尾 /zhang$/ 等价 ‘%zhang’ 、 /zhang/i 忽略大小写 |
是否存在 | db.t_user.find({“age”:{$exists:true}}); | 查询存在age字段的记录。查不存在的改为false即可 |
下面是一些对 “查询结果” 再做处理的方法
操作 | mongdb SQL | 关系型SQL | 备注 |
---|---|---|---|
数据格式化 | db.t_user.find().pretty(); | 相当于json格式化 | |
去重 | db.t_user.find().distinct(“name”); | select distinct name from t_user; | |
统计行数 | db.t_user.find().count(); | select count(*) from t_user | |
求和 | db.t_user.aggregate([{$ group:{_id:null,age:{$ sum:“$age”}}}]); | select sum(age) from t_user | 类似的,求平均值把sum改成avg。 其他还有min、max、push(把查询结果方数组里)、first(取第一个)、last |
查前N条 | db.t_user.find().limit(10); | select * from t_user limit 10 或者 select top 10 * from t_user | 展示前10条 |
不要前N条 | db.t_user.find().skip(10); | select * from t_user where rowId > 10 | 前10条舍弃不要 |
排序 | db.t_user.find().sort({age:-1}); | select * from t_user order by age desc | 1正序 -1倒序 |
分页 | db.t_user.find().skip(10).limit(10) | select * from t_user limit 10, 20; | 第pageNo页时,skip=(pageNo-1)*pageSize,limit=pageSize (pageNo是当前页码 pageSize是每页条数 ) |
分页+排序 | db.t_user.find().skip(10).limit(10).sort({age:-1}); | select * from t_user limit 10, 20 order by age desc | skip(), limilt(), sort()这三个的执行顺序是先sort(),然后是skip(),最后是limit() |
分组 | db.t_user.find({$ group:{name: ‘$name’}}); | select * from t_user group by name; | |
查子集 | db.t_user.find({},{“name”:{“$slice”:10}}) | select * from t_user limit 10 | slice可从结果集里(根据某个字段)得到子集;10表查前10条,-10表示查后10条,[10,20] 表示查区间 |
下面是一些有用的javascript语法
操作 | mongdb SQL | 备注 |
---|---|---|
查某个key存在 | db.t_user.find({“age”:{$exists:true}}); | 不存在改成false |
过滤key不存在的记录 | db.t_user.find({age:{“$ in”:[null], “$ exists”:true}}) | age = null或age不存在的都会被查询出来,通过exists过滤不存在只留下age=null的 |
定义参数的查询 | var start = new Date(“11/03/2023”); // 定义变量并赋值 db.t_user.find({createTime:{$ lte:start}}) // 根据按时间查询 | 或者 db.t_user.find({createTime:{$gt:ISODate(“2023-03-11T00:00:00Z”)}}); |
既有where条件同时有函数 | db.t_user.aggregate([{$ match:{createTime:{$ gte:ISODate(“2020-11-10T00:00:00Z”),$ lt:ISODate(“2020-11-11T00:00:00Z”)}}},{$ group:{_id:null,age:{$ sum:“$age”}}}]) | 等同SELECT SUM(age) from t_user where createTime >= ‘2020-11-10 00:00:00’ and createTime < ‘2020-11-11 00:00:00’; |
下面是一些拓展功能参考
# 遍历集合 注:游标10分钟内没有使用会自动销毁(immortal函数可设置超时不销毁)
var cursor=db.t_user.find(); //定义游标,使用forEach循环
cursor.forEach(function(f){
print(f.name,f.age); // 循环打印姓名 年纪
});
或者
var cursor=db.t_user.find(); //定义游标
while(cursor.hasNext()){
var f = cursor.next();
print(f.name,f.age); // 循环打印姓名 年纪
}
# 随机查询一条 等价SELECT * FROM t_user ORDER BY RAND() limit 1
var total = db.t_user.count(); // 查询总数
var random = Math.floor(Math.random()*total); // 根据总数取个随机值random
db.t_user.skip(random).limit(1); // 前random条舍弃,从剩下的里面取第一条
# 插入数据
db.t_user.insert([
{ "_id" : 1, "userId" : "u1", "name" : "zhangsan", "age" : "15" },
{ "_id" : 2, "userId" : "u2", "name" : "lisi", "age" : "22" }
]);
关于insert、insertOne、insertMany、save的区别
insert和insertMany 一次可以插入多条。可以搭配{ordered:true}使用。ordered为是否按顺序写入之意,默认true。即中间某条插入失败时,true则中断不执行后续,false可以继续执行后面的
insertOne和save 一次只能插入一条,多条报错。且前者若主键冲突报错,后者则覆盖旧数据
# 关联查询 类似于 select info.* from t_user_info info left join t_user u on info.user_id = u.user_id where info.name = 'zhangsan'
db.t_user_info.aggregate([
{
$lookup: # 表示表关联查询
{
from: "t_user", # 被关联的表名称
localField: "user_id", # 关联字段:t_user_info.user_id
foreignField: "user_id", # 关联字段: t_user.user_id
as: "userInfo" # 结果集别名
}
},
{ $match : {"name" :"zhangsan"} } # where条件进行过滤
])
# 根据姓名分组查数量 select name as _id, count(*) as num from t_user group by name
db.t_user.aggregate([
{
$group: { # 分组
_id: '$name', # 根据什么字段字段进行分组,这里是根据name字段。'$name'也可以改成null表示只分一个组,目的一般用于求和求平均数等场景
num: {$sum: 1} # 每个分组数量 * 1 (1不是固定值可以改成别的数字)
# ageArray: {$push: '$age'} # 把每个组的age字段放在ageArray这个数组字段里面, 所以push有点类似wm_concat()函数,数组拼接和逗号拼接的格式区别而已
}
}
])
# 综合查询 select name, age from t_user where age > 20 group by name limit 10,20 order by name desc
db.t_user.aggregate([
{
$project: { // 需要查询哪些字段
_id: 0, // _id字段不查
name: 1 // name和age字段查
age: 1
}
},
{
$match: {
age: {$gt: 20} // 匹配条件 年纪大于20的
}
},
{
$group: {
name: '$name', // 根据name分组
}
},
{
$sort: {
name: -1 // 根据name倒叙
}
},
{
$skip: 10
},
{
$limit: 10
}
])
查询用 find(普通查询) 和 aggregate(聚合查询) 都可以,但后者的效率好一点。find是用{}来接收查询条件,aggregate用数组[]来接收查询条件。如果用aggregate,根据下面表格可以快速记忆下来,配合上面的示例就可以写出符合需求的脚本语句了。
关系型数据库 关键词 | monggodb 关键词 |
---|---|
where/having | match |
group by | group |
order by | sort |
sum/count | sum |
join | lookup |
concat | push |
limit | limit |
max | max |
min | min |