MongoDB是一个介于关系型数据库和菲关系型数据库之间的产品,其最大的特点是它支持的查询语言非常强大,且其语法有点类似面向对象的查询语言几乎可以实现类似关系型数据库单表查询的绝大部分功能。
下面是我本人练习MongoDB数据库基本语法(查询篇)的JavaScript代码(编辑环境:Robo 3T-1.2 绿色版):
/***************批量插入数据*****************/
user1 = {
"_id":1,
"name":"zhangsan",
"age":1,
"hobbies":["music", "read"],
"addr":{
"country":"China",
"city":"BJ"
}
}
user2 = {
"_id":2,
"name":"lisi",
"age":2,
"hobbies":["music", "read"],
"addr":{
"country":"China",
"city":"SH"
}
}
user3 = {
"_id":3,
"name":"wangwu",
"age":3,
"hobbies":["music", "read"],
"addr":{
"country":"China",
"city":"GZ"
}
}
user4 = {
"_id":4,
"name":"zhaoliu",
"age":4,
"hobbies":["music", "read"],
"addr":{
"country":"China",
"city":"SZ"
}
}
user5 = {
"_id":5,
"name":"tianqi",
"age":5,
"hobbies":["music", "read"],
"addr":{
"country":"China",
"city":"TY"
}
}
db.user.insertMany([user1, user2, user3, user4, user5])
/**
*1、查询所有
*/
db.ser.find() //等同于db.user.find({})
db.user.distinct("age")//去重
db.user.find().pretty()//格式化的方式来显示所有文档
//select * from user where id != 3
/**
*3、比较查询
* =,!= ('$ne') ,> ('$gt') ,< ('$lt') ,>= ('$gte') ,<= ('$lte')
*/
//select * from user where id = 3
db.user.find({"_id":3})
//select * from user where id != 3
db.user.find({"_id":{"$ne":3}})
//select * from user where id > 3
db.user.find({"_id":{"$gt":3}})
//select * from user where age < 3
db.user.find({"_id":{"$lt":3}})
//select * from user where id >= 3
db.user.find({"_id":{"$gte":3}})
//select * from user where id <= 3
db.user.find({"_id":{"$lte":3}})
/**
*3、逻辑查询
* $and,$or,$not
*/
// select * from user where id >=3 and id <=4;
db.user.find({"_id":{"$gte":3,"$lte":4}})
// select * from user where id >=3 and id <=4 and age >=4;
db.user.find({
"_id":{"$gte":3,"$lte":4},
"age":{"$gte":4}
})
db.user.find({
"$and": [
{"_id": {"$gte":3, "$lte":4}},
{"age": {"$gte":4}}
]
})
// select * from user where id >=0 and id <=1 or id >=4 or name = "tianqi";
db.user.find({
$or: [
{"_id": {$gte:0, $lte:1}},
{"_id": {$lte:4}},
{"name": "tianqi"}
]
})
// select * from user where id % 2 = 1;
db.user.find({"_id":{"$mod":[2,1]}})
//上一条取反
db.user.find({
"_id":{"$not":{"$mod":[2,1]}}
})
/**
*4、成员查询
* $in , $nin
*/
// select * from user where age in (1,2,3);
db.user.find({"age":{"$in":[1,2,3]}})
// select * from user where name not in ("zhangsan","lisi");
db.user.find({"name":{"$nin":["zhangsan","lisi"]}})
/**
*5、$type操作符查询
* MongoDB可以使用的类型操作符:1-Double、2-String、3-Object、4-Array、5-Binary Data、8-Boolan、9-Date ...
*/
// 查询name是字符串类型的数据
db.user.find({name:{$type:2}})
/**
*6、正则查询
* 正则定义在/ /内
*/
// select * from user where name regexp '^z.*?(u|i)$';
// 匹配规则:z开头、n或u结尾,不区分大小写
db.user.find({'name':/^z.*?(n|u)$/i})
/**
*7、投影查询
* 1用来显示字段而0是用来隐藏字段,_id会默认显示出来。
*/
// select name,age from user where id=3;
db.user.find({'_id':3},{'_id':0,'name':1,'age':1})
// select name,age from user where name regexp "^z.*(n|u)$";
db.user.find({
"name":/^z.*(n|u)$/i
},
{
"_id":0,
"name":1,
"age":1
}
)
/**
*8、数组查询
* 查询数组相关
*/
// 查hobbies中有dancing的人
db.user.find({
"hobbies":"music"
})
// 查看既有dancing爱好又有tea爱好的人
db.user.find({
"hobbies":{"$all":["music","read"]}
})
// 查看索引第2个爱好为dancing的人
db.user.find({
"hobbies.2":"read"
})
// 查看所有人的第1个到第3个爱好,第一个{}表示查询条件为所有,第二个是显示条件
db.user.find(
{},
{
"_id":0,
"name":0,
"age":0,
"addr":0,
"hobbies":{"$slice":[0,2]},
}
)
// 查看所有人最后两个爱好,第一个{}表示查询条件为所有,第二个是显示条件
db.user.find(
{},
{
"_id":0,
"name":0,
"age":0,
"addr":0,
"hobbies":{"$slice":-2},
}
)
// 查询子文档有"country":"China"的人
db.user.find(
{
"addr.country":"China"
}
)
/**
*9、排序查询
* 1 为升序排列,而-1是用于降序排列
*/
// 按姓名正序
db.user.find().sort({"name":1})
// 按年龄倒序 按id正序
db.user.find().sort({"age":-1,'_id':1})
/**
*10、分页查询
* limit表示取多少个document,skip代表跳过几个document
* 分页公式:db.user.find().skip((pageNum–1)*pageSize).limit(pageSize)
*/
db.user.find().limit(2).skip(0) // 前两个
db.user.find().limit(2).skip(2) // 第三个和第四个
db.user.find().limit(2).skip(4) // 第五个和第六个
/**
*11、统计查询
*/
// 查询_id大于3的人数
// 方式一
db.user.count({'_id':{"$gt":3}})
// 方式二
db.user.find({_id:{"$gt":3}}).count()
/**
*11、聚合查询
* 在MongoDB中聚合为aggregate,聚合函数主要用到$match $group $avg $project $concat,可以加"$match"也可以不加$match
*/
// 练习Aggregate语法,先插入如下数据:
emp1 = {"_id":1,"name":"武大郎","sex":"male","age":18,"hire_date":"20170301","post":"烧饼检察官","salary":7300.33}
emp2 = {"_id":2,"name":"武松","sex":"male","age":78,"hire_date":"20150302","post":"公务员","salary":71000000.31}
emp3 = {"_id":3,"name":"宋江","sex":"male","age":81,"hire_date":"20130305","post":"公务员","salary":78300}
emp4 = {"_id":4,"name":"林冲","sex":"male","age":73,"hire_date":"20140701","post":"公务员","salary":73500}
emp5 = {"_id":5,"name":"林冲","sex":"male","age":73,"hire_date":"20140701","post":"公务员","salary":73500}
emp6 = {"_id":6,"name":"柴进","sex":"male","age":28,"hire_date":"20121101","post":"公务员","salary":72100}
emp7 = {"_id":7,"name":"卢俊义","sex":"female","age":18,"hire_date":"20110211","post":"公务员","salary":79000}
emp8 = {"_id":8,"name":"高俅","sex":"male","age":18,"hire_date":"19000301","post":"公务员","salary":730000}
emp9 = {"_id":9,"name":"鲁智深","sex":"male","age":48,"hire_date":"20101111","post":"公务员","salary":710000}
emp10 = {"_id":10,"name":"史进","sex":"female","age":48,"hire_date":"20150311","post":"打手","salary":73000.13}
emp11 = {"_id":11,"name":"李逵","sex":"female","age":38,"hire_date":"20101101","post":"打手","salary":72000.35}
emp12 = {"_id":12,"name":"周通","sex":"female","age":18,"hire_date":"20110312","post":"打手","salary":71000.37}
emp13 = {"_id":13,"name":"石秀","sex":"female","age":18,"hire_date":"20160513","post":"打手","salary":73000.29}
emp14 = {"_id":14,"name":"李忠","sex":"female","age":28,"hire_date":"20170127","post":"打手","salary":74000.33}
emp15 = {"_id":15,"name":"吴用","sex":"male","age":28,"hire_date":"20160311","post":"文人","salary":710000.13}
emp16 = {"_id":16,"name":"萧让","sex":"male","age":18,"hire_date":"19970312","post":"文人","salary":720000}
emp17 = {"_id":17,"name":"安道全","sex":"female","age":18,"hire_date":"20130311","post":"文人","salary":719000}
emp18 = {"_id":18,"name":"公孙胜","sex":"male","age":18,"hire_date":"20150411","post":"文人","salary":718000}
emp19 = {"_id":19,"name":"朱贵","sex":"female","age":18,"hire_date":"20140512","post":"文人","salary":717000}
db.emp.insertMany([emp1, emp2, emp3, emp4, emp5, emp6, emp7, emp8, emp9, emp10, emp11, emp12, emp13, emp14, emp15, emp16, emp17, emp18, emp19])
/**
*$match和$group
**/
// {"$match":{"字段":"条件"}},可以使用任何常用查询操作符$gt,$lt,$in等
// select * from db1.emp where post='公务员';
db.emp.aggregate([{"$match":{"post":"公务员"}}])
// select * from db1.emp where id > 3 group by post;
db.emp.aggregate([
{"$match":{"_id":{"$gt":3}}},
{"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}
])
// select * from db1.emp where id > 3 group by post having avg(salary) > 10000;
db.emp.aggregate([
{"$match":{"_id":{"$gt":3}}},
{"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}},
{"$match":{"avg_salary":{"$gt":10000}}}
])
// {"$group":{"_id":分组字段,"新的字段名":聚合操作符}}
// 将分组字段传给$group函数的_id字段即可
//{"$group":{"_id":"$sex"}} #按照性别分组
//{"$group":{"_id":"$post"}} #按照职位分组
//{"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多个字段分组,比如按照州市分组
// 分组后聚合得结果,类似于sql中聚合函数的聚合操作符:$sum、$avg、$max、$min、$first、$last
//例1:select post,max(salary) from db1.emp group by post;
db.emp.aggregate([{"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}}])
//例2:取每个部门最大薪资与最低薪资
db.emp.aggregate([{"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}}])
//例3:如果字段是排序后的,那么$first,$last会很有用,比用$max和$min效率高
db.emp.aggregate([{"$group":{"_id":"$post","first_id":{"$first":"$_id"}}}])
//4:求每个部门的总工资
db.emp.aggregate([{"$group":{"_id":"$post","count":{"$sum":"$salary"}}}, {"$sort": {"count": 1}}])
//5:求每个部门的人数
db.emp.aggregate([{"$group":{"_id":"$post","count":{"$sum":1}}}, {"$sort": {"count": 1}}])
// 数组操作符
// {"$addToSet":expr}#不重复
// {"$push":expr}#重复
// 查询岗位名以及各岗位内的员工姓名:select post,group_concat(name) from db1.emp group by post;
// 重复的也查询出来
db.emp.aggregate([{"$group":{"_id":"$post","names":{"$push":"$name"}}}])
// 查询结果
/* 1 */
{
"_id" : "文人",
"names" : [
"吴用",
"萧让",
"安道全",
"公孙胜",
"朱贵"
]
}
/* 2 */
{
"_id" : "打手",
"names" : [
"史进",
"李逵",
"周通",
"石秀",
"李忠"
]
}
/* 3 */
{
"_id" : "公务员",
"names" : [
"武松",
"宋江",
"林冲",
"林冲",
"柴进",
"卢俊义",
"高俅",
"鲁智深"
]
}
/* 4 */
{
"_id" : "烧饼检察官",
"names" : [
"武大郎"
]
}
// 查询不重复的,如果有重复的保留一个
db.emp.aggregate([{"$group":{"_id":"$post","names":{"$addToSet":"$name"}}}])
// 查询结果
/* 1 */
{
"_id" : "文人",
"names" : [
"吴用",
"朱贵",
"萧让",
"安道全",
"公孙胜"
]
}
/* 2 */
{
"_id" : "打手",
"names" : [
"李忠",
"史进",
"李逵",
"周通",
"石秀"
]
}
/* 3 */
{
"_id" : "公务员",
"names" : [
"鲁智深",
"高俅",
"宋江",
"林冲",
"卢俊义",
"武松",
"柴进"
]
}
/* 4 */
{
"_id" : "烧饼检察官",
"names" : [
"武大郎"
]
}
/**
* $project
**/
//{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}
// select name,post,(age+1) as new_age from db1.emp;
db.emp.aggregate([
{
$project:{
"name":1,
"post":1,
"new_age":{"$add":["$age",1]}
}
}
])
/**
* $sort和$limit和$skip
**/
// 排序:{"$sort":{"字段名":1,"字段名":-1}} #1升序,-1降序
// 限制:{"$limit":n}
// 跳过:{"$skip":n} #跳过多少个文档
// 取平均工资最高的前两个部门
db.emp.aggregate([
{
"$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
},
{
"$sort":{"平均工资":-1}
},
{
"$limit":2
}
])
// 取平均工资最高的第二个部门
db.emp.aggregate([
{
"$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
},
{
"$sort":{"平均工资":-1}
},
{
"$limit":2
},
{
"$skip":1
}
])
/**
* $sample
**/
// 随机获取3个文档
db.emp.aggregate([
{$sample: {size:3}}
])
/**
* $concat和$substr和$toLower和$toUpper
**/
// 截取字符串
db.emp.aggregate([
{
$project:{
"_id":0,
"str": {$substr: ["$sex", 0, 2]}
}
}
])
// 拼接
db.emp.aggregate([
{
$project:{
"name":1,
"post":1,
"name_sex": {$concat: ["$name", "测试拼接", "$sex"]}
}
}
])
// 将性别的英文转为大写
db.emp.aggregate([{"$project":{"sex":{"$toUpper":"$sex"}}}])
/**
*12、索引
* 索引通常能够极大的提高查询的效率,MongoDB使用 ensureIndex()方法来创建索引
*/
db.COLLECTION_NAME.ensureIndex({KEY:1})
// 语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,-1则为按降序来创建索引。
db.user.ensureIndex({"name":-1})
// 我们可以指定所建立索引的名字,如下所示:
db.user.ensureIndex({"name":1},{"name":"nameIndex"})
//查询索引的语法格式如下所示:
db.COLLECTION_NAME.getIndexes()
db.user.getIndexes()
//删除索引的语法格式如下所示:
db.COLLECTION_NAME.dropIndex(INDEX_NAME)
db.user.dropIndex("nameIndex")