mongodb常见操作
-
MongoDB是目前noSQL中比较火的数据库,优劣势都很明显。
优势:灵活操作,可扩展性强,使用简单,只要你会js,轻松操作
劣势:不适合小型项目,放几条数据大小就几十M。数据回滚不方便 - 启动数据库
./mongod --dbpath ~/mongoData/db --port 27017 --logs ~/mongoData/log
--dbpath 设置数据保存的位置
--logs 设置数据库操作记录
--port 数据库启动的端口 - 辅助工具Robomongo
超好用的mongodb图形化工具,可以直观的查看数据,也可以直接右键编辑想要修改的数据,这点确实是比较方便的,不过目前有些不爽的地方就是不支持es6
注意事项:robomongo默认数据每页是50条数据;目前默认查询的最大数据量是16M,一般可通过limit分批操作
基础操作 (增删改查)
- 新增数据
db.collectionName.insert()
插入一条数据的实例如下;然后使用find查询结果,这里可以看到给我们分配了一个 _id 的属性,这是这条数据的位置标识,当然这里也可以在插入的时候增加自己的 _id 字段
插入数据
插入结果
-
修改数据
- 基础操作
db.collection.update( <query>, <update>, { upsert: <boolean>, multi: <boolean> } )
query: 查询条件
update: 更新字段,常用两个操作符为$set:更新字段; $unset:删除某字段
upsert: 设置为true时,如果没有找到查询条件对应的数据时,就插入这条数据,默认值为false
multi:设置为true时更新所有查找到的数据,默认值为false,只更新找到的第一条eg: 把刚插入的数据年龄修改为12
db.users.update({name: 'jack'}, {$set: {age: 12}})
eg: 删除用户jack的年龄字段db.users.update({name: 'jack'}, {$unset: {age: true}})
后面的参数都很简单的,试一下就ok啦
删除数据
db.user.remove(<query>)
query删除满足条件的数据-
查询数据
db.user.find(<query>, <field>)
query: 筛选条件,常用的操作符$gt,$lt,$ne,$in等等,这些看一下文档就知道怎么写了
field: 用来选出所需的数据
下图为一个简单的查询,查询年龄小于25的护具,并且只需要数据的中的age字段,返回结果如图
find简单实例
db.users.find().count()
如需查询满足条件的数据有多少条,在后面加上count进行统计,这些都是一些最基本的操作,网上教程很多,推荐基础看一看菜鸟教程,这篇基础讲的很详细
稍复杂的操作
先给出四个collection的数据,然后按操作符按需完成例,==每次操作后均将数据还原==。
数据如下,之后的操作都基于这些数据
users表,用户保存用户信息,保存用户名称,年龄信息
/* 1 */
{
"_id" : ObjectId("592ee1871855e63d5a44e614"),
"name" : "jack",
"age" : 24.0
}
/* 2 */
{
"_id" : ObjectId("592ee2691855e63d5a44e615"),
"name" : "rose",
"age" : 27.0
}
orders表,用于保存订单信息,存有订单总价,订单创建时间,订单状态,订单用户id及订单详情
/* 1 */
{
"_id" : ObjectId("592ecb0c1855e63d5a44e609"),
"amount" : 22000,
"user_id" : ObjectId("592ee1871855e63d5a44e614"),
"create_time" : ISODate("2017-06-04T04:43:58.769Z"),
"status" : "success",
"goods" : [
{
"name" : "《javascript权威指南》",
"type" : "book",
"price" : 50.0,
"number" : 2,
"good_id" : ObjectId("592ecb9d1855e63d5a44e60b")
},
{
"name" : "iphone 7",
"type" : "phone",
"price" : 7000,
"number" : 3,
"good_id" : ObjectId("592ecb821855e63d5a44e60a")
}
]
}
/* 2 */
{
"_id" : ObjectId("592ecd7b1855e63d5a44e60f"),
"amount" : 4080,
"user_id" : ObjectId("592ee2691855e63d5a44e615"),
"create_time" : ISODate("2017-06-04T04:43:58.769Z"),
"status" : "success",
"goods" : [
{
"name" : "Moto Z",
"type" : "phone",
"price" : 4000.0,
"number" : 1,
"good_id" : ObjectId("592ecbdf1855e63d5a44e60d")
},
{
"name" : "《shell编程》",
"type" : "book",
"price" : 40.0,
"number" : 2,
"good_id" : ObjectId("592ecbb61855e63d5a44e60c")
}
]
}
/* 3 */
{
"_id" : ObjectId("5932bcd90682be14a892ea13"),
"amount" : 8000.0,
"user_id" : ObjectId("592ee1871855e63d5a44e614"),
"create_time" : ISODate("2017-06-04T04:43:58.769Z"),
"goods" : [
{
"name" : "Moto Z",
"type" : "phone",
"price" : 8000.0,
"number" : 2.0,
"good_id" : ObjectId("592ecbdf1855e63d5a44e60d")
}
]
}
goods表,保存商品信息,存有商品名称,类型,单价,厂商信息
/* 1 */
{
"_id" : ObjectId("592ecb821855e63d5a44e60a"),
"name" : "iphone 7",
"type" : "phone",
"price" : 7000.0,
"company" : "iphone"
}
/* 2 */
{
"_id" : ObjectId("592ecb9d1855e63d5a44e60b"),
"name" : "《javascript权威指南》",
"type" : "book",
"price" : 55.0,
"company" : "XXX出版社"
}
/* 3 */
{
"_id" : ObjectId("592ecbb61855e63d5a44e60c"),
"name" : "《shell编程》",
"type" : "book",
"price" : 40.0,
"company" : "XXX出版社"
}
/* 4 */
{
"_id" : ObjectId("592ecbdf1855e63d5a44e60d"),
"name" : "Moto Z",
"type" : "phone",
"price" : 4000.0,
"company" : "联想"
}
update数组内数据
需求: 订单ObjectId("592ecb0c1855e63d5a44e609"),追加一本《javascript权威指南》
方法1:db.orders.update({_id: ObjectId("592ecb0c1855e63d5a44e609")}, {$set: {"goods.0.number": 3}})
方法2:db.orders.update({_id: ObjectId("592ecb0c1855e63d5a44e609"), 'goods.good_id': ObjectId("592ecb9d1855e63d5a44e60b")}, {$set: {'goods.$.number': 3}})
-
$exists
需求: 将所有订单的"create_time"字段更新为当前时间
$exists: 判断是否存在var time = new Date(); db.orders.update({_id: {$exists: true}}, {$set: {create_time: time}}, {multi: true})
-
aggregate,$match,$project 聚合
$aggregate: 聚合操作,可以理解为链式操作,将一系列的操作放到一个数组里,依次执行,这玩意经常用到的,
$match: 通常和aggregate配合使用,其作用是匹配查询条件,和find语句中的第一个查询参数一个作用
$project: 和find语句中第二个参数效果一样,选出自己所需的字段
需求:需要订单金额大于10000的订单时间和订单金额数据db.orders.aggregate([ {$match: {amount: {$gt: 10000}}}, {$project: { amount: 1, create_time: 1 }} ])
-
$unwind 解璇
$unwind: 简单的用公式大概就是这个意思了,{key: [v1, v2]} => {key: v1}, {key: v2}
需求: 拿到订单里面所有类型为book的数据db.orders.aggregate([ {$unwind: '$goods'}, {$match: {'goods.type': 'book'}} ])
-
$skip, $limit,$sort常用于前端的列表页
$skip: 忽略查询到的数据
$limit: 限制数据条数
$sort: 排序
需求: 假如前端一页展示一条数据,订单总价降序排列,现在需要第二页的数据db.orders.aggregate([ {$sort : { amount : -1}}, {$skip: 1}, {$limit: 1} ])
==这里面也有坑的,一定要结合使用场景正确排序==
-
$group, $sum, $multiply分组统计
$group: 分组,一般用于统计,可以按字段或者对象分组
$sum: 累加求和
$multiply: 乘法,减减乘除等mongo的文档都有,多看看文档
需求: 统计订单中不同商品的销售额,各个商品出现在订单中的次数db.orders.aggregate([ {$unwind: '$goods'}, {$group: { _id: '$goods.good_id', total: {$sum: {$multiply: ["$goods.price", "$goods.number"]}}, count: {$sum: 1} }} ])
-
$lookup 联表
$lookup: 与其他表进行关联,接受四个参数
from: 需要关联的集合名称
localField: 本集合的关联字段
foreignField: 关联的集合字段
as:将结果做为神马字段,这里返回的是一个数组
需求,查看年龄大于20的各用户的订单情况db.users.aggregate([ {$match: {age: {$gt: 20}}}, {$lookup: { from: 'orders', localField: '_id', foreignField: 'user_id', as: 'orders' }} ])
-
$cond
$cond mongo中的if判断语句
需求:统计订单成功的总额,判断状态为success的数据db.orders.aggregate([ {$group: { _id: null, total: { $sum: { $cond: { if: {$eq: ["$status", "success"]}, then: "$amount", else: 0 } } } }} ])
-
$size 数组长度
需求:每个订单中有多少不同的额商db.orders.aggregate([ {$project: { count: {$size: "$goods"} }} ])
其他常用的
$push: 向数组中添加数据
$max, $min, $avg: 最大最小值, 平均值
**$dateToString **: 时间格式化
$concat: 字符串拼接{ $concatArrays: [ [ "hello", " "], [ "world" ] ] } => [ "hello", " ", "world" ]
$concatArrays: 数组拼接
$filter: 过滤数组
$slice: 剪切数组{ $slice: [ [ 1, 2, 3 ], 1, 1 ] } => [ 2 ]
$and, $or: 与或判断
==这些加上比较和运算的操作符基本就是最常用的了,掌握了基本操作没有问题==
小技巧
- 在后台添加索引,简单理解就是在数据库不忙的时候执行
db.collectionName.createIndex(<query>,{background:true})
- 将mongo的文档数据导入excel,下图的结果可以直接copy到excel中,格式不会乱
db.goods.find().map(function(item) { return [item.name, item.type, item.price, item.company].join('\t')
}).join('\n')
```
- 将打包好的数据库移植到另一台pc使用
第一步:启动mongodb服务器mongod -port yourPort --dbpath yourPath
第二步:执行命令type 数据包|mongorestore --host localhost:yourPort --drop --gzip --archive -vvvv --stopOnError