2019独角兽企业重金招聘Python工程师标准>>>
本文对 MongoDB 的一些基本操作做一下整理和总结。 首先会介绍一下基于命令行的sql操作,其次结合 spring 的 mongoTemplate 介绍一下如何通过 java 操作数据库。对 NoSQL 不熟悉的同学可以了解一下。
1.版本
MongoDB 3.4.2
2.安装
安装 MongoDB 可以查看我的另外一篇文章 CentOs7 急速安装 MongoDB
3.创建用户
关于用户创建和维护可以查看我的另外一遍文章 MongoDB 3.4.7 用户基本操作
4.命令行CRUD操作
这以 testUser 这个集合为例子,下面的操作都是基于这个集合。
4.0 示例
下面分享2个别人的教程,一个是官网的例子,一个是菜鸟教程。如果看我的内容有疑惑的话可以参考这2个教程。
官网示例(英文) 菜鸟教程(中文)
4.1 插入
语法格式:
db.COLLECTION_NAME.insert(document)
例子:
> db.getCollection('testUser').insert({
name: 'a',
description: 'user a',
age: 15,
zone: 'shanghai'
})
WriteResult({ "nInserted" : 1 })
>
4.2 更新
语法格式:
db.collection.update(, , { upsert: , multi: , writeConcern: } )
例子:
查出 name 字段为 a 的记录,更新 zone 字段为 hangzhou
> db.getCollection('testUser').update({
name: 'a'
}, {
$set: {
zone: 'hangzhou'
}
})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
这里需要注意, update 一共提供5个参数
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
所以上面的例子update只会更新一条数据,如果需要更新多条,需要将第4个参数设置为true
db.getCollection('testUser').update({
name: 'a'
}, {
$set: {
zone: 'hangzhou'
}
}, false, true)
第3个参数 upsert 的意思是,如果根据条件查到记录了就更新该记录,如果没有查到记录就插入一条记录。
4.3 删除
语法:
db.collection.remove(, )
例子:
移除 name 字段为 a 的记录
>db.getCollection('testUser').remove({
name: 'a'
})
4.4 查询
语法:
db.collection.find(query, projection)
例子:
查询 name 为 a 的记录
db.getCollection('testUser').find({
name: 'a'
})
查询 name 为 a, age 大于 14 的记录
db.getCollection('testUser').find({
name: 'a', age: {$gt: 14}
})
还有一些 in or nin gt lt gte 等 大家可以意会一下,实在悟不出来可以点击这里
4.5 排序
语法:
db.COLLECTION_NAME.find().sort({KEY:1})
例子:
查询 name 为 a, age 大于 14 的记录, 按age升序排序。1 为升序,-1 为降序
db.getCollection('testUser').find({
name: 'a', age: {$gt: 14}
}).sort({age:1})
4.6 索引
语法:
db.COLLECTION_NAME.ensureIndex({KEY:1})
例子:
为 zone 字段添加升序索引,并且在后台执行
db.getCollection('testUser').ensureIndex({zone:1}, {background: true})
查看索引
db.getCollection('testUser').getIndexes()
5.命令行聚合操作
聚合操作语法就有点复杂了,结合mysql语法讲解一下
mysql
select zone, count(zone) from testUser group by zone
mongo
> db.getCollection('testUser').aggregate([{
$group: {
_id: "$zone",
num_total: {
$sum: 1
}
}
}])
{ "_id" : "hangzhou", "num_total" : 1 }
{ "_id" : "guangzhou", "num_total" : 500000 }
{ "_id" : "beijing", "num_total" : 2800000 }
{ "_id" : "shanghai", "num_total" : 400001 }
可以看到我这一个表里面有300多万数据,这个聚合执行下来 4.6 秒,还是挺快的。
mysql
select zone, count(zone) from testUser where age <= 15 group by zone
mongo
> db.getCollection('testUser').aggregate([
{
$match: {
age: {$lte: 15}
}
},
{
$group: {
_id: "$zone",
count: {
$sum: 1
}
}
}
]);
{ "_id" : "hangzhou", "count" : 1 }
{ "_id" : "guangzhou", "count" : 500000 }
{ "_id" : "beijing", "count" : 2800000 }
{ "_id" : "shanghai", "count" : 400001 }
mysql
select zone, avg(age), count(zone) from testUser where age <= 15 group by zone
mongo
> db.getCollection('testUser').aggregate([
{
$match: {
age: {$lte: 15}
}
},
{
$group: {
_id: "$zone",
avg: {
$avg: '$age'
},
count: {
$sum: 1
}
}
}
]);
{ "_id" : "hangzhou", "avg" : 15, "count" : 1 }
{ "_id" : "guangzhou", "avg" : 15, "count" : 500000 }
{ "_id" : "beijing", "avg" : 15, "count" : 2800000 }
{ "_id" : "shanghai", "avg" : 15, "count" : 400001 }
详细的讲解猛戳这里
6.命令行非交互式执行sql
/xxx/mongodb-osx-x86_64-3.4.2/bin/mongo -u -p --eval "db.getCollection('xxxx').find({})"
7.使用MongoTemplate操作数据库
7.1 插入
TestUser testUser = new TestUser();
testUser.setUserId(1);
testUser.setUsername("a");
testUser.setAge(15);
testUser.setZone("beijing");
mongoTemplate.save(testUser);
7.2 查询全部
List testUserList = mongoTemplate.find(new Query(), TestUser.class);
7.3 条件查询
Query query = new Query();
query.addCriteria(Criteria.where("zone").is("shanghai"));
List testUserList = mongoTemplate.find(query, TestUser.class);
7.4 更新一条
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(1));
Update update = new Update();
update.set("age", 22);
mongoTemplate.updateFirst(query, update, TestUser.class);
7.5 更新插入
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(1));
Update update = new Update();
update.set("age", 22);
mongoTemplate.upsert(query, update, TestUser.class);
7.6 更新多条
Query query = new Query();
query.addCriteria(Criteria.where("userId").is(1));
Update update = new Update();
update.set("age", 22);
mongoTemplate.updateMulti(query, update, TestUser.class);
7.7 带条件聚合
Aggregation aggregation = newAggregation(
match(Criteria.where("zone").is("guangzhou")),
group().avg("age").as("avg_age").count().as("count")
);
AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation, "testUser", HashMap.class);
List rs = aggregationResults.getMappedResults();
查询 zone 等于 guangzhou 的记录,按 zone 统计条数和平均年龄
7.8 无条件聚合
Aggregation aggregation = newAggregation(
group("zone").count().as("count")
);
AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation, "testUser", HashMap.class);
List rs = aggregationResults.getMappedResults();
按 zone 统计条数
7.9 删除
TestUser testUser = new TestUser();
testUser.setUserId(i);
testUser.setUsername("a");
testUser.setAge(15);
testUser.setZone("beijing");
mongoTemplate.remove(testUser);
8. 运行中异常
看到别人遇到过 groupby 产生的超出内存大小的限制,但是自己没有复现出来。就放2个地址记录下别人的经验。
http://www.codeweblog.com/mongodb-groupby%E6%93%8D%E4%BD%9C-%E7%BB%93%E6%9E%9C%E9%9B%86%E5%A4%A7%E5%B0%8F%E9%99%90%E5%88%B6%E9%97%AE%E9%A2%98/
https://www.cnblogs.com/viaiu/p/4848445.html