NoSQL与SQL的区别:
MongoDB基于灵活的JSON文档模型(从错综复杂的关系模型到对象模型)。适合敏捷开发,能快速响应业务变化。其高可用(自恢复、多中心容灾能力)、高水平扩展能力(横向无缝扩展,多种数据分布策略,分片,TB-PB级别)使得在处理海量、高并发的数据应用时颇具优势。
游戏(积分、装备);物流(订单);社交(朋友圈、地点、附近的人);物联网(设备信息、日志);视频直播(用户信息、礼物);大数据;CRM、ERP
命令:mongoimport --db dbname --type json xxx.json
(也可以是jsonArray的形式导入)
示例:mongoimport --db test_db --type json product.json
以下是 products.json 文件
{ "_id" : "ac3", "name" : "AC3 Phone", "brand" : "ACME", "type" : "phone", "price" : 200, "rating" : 3.8,"warranty_years" : 1, "available" : true }
{ "_id" : "ac7", "name" : "AC7 Phone", "brand" : "ACME", "type" : "phone", "price" : 320, "rating" : 4,"warranty_years" : 1, "available" : false }
{ "_id" : { "$oid" : "507d95d5719dbef170f15bf9" }, "name" : "AC3 Series Charger", "type" : [ "accessory", "charger" ], "price" : 19, "rating" : 2.8,"warranty_years" : 0.25, "for" : [ "ac3", "ac7", "ac9" ] }
{ "_id" : { "$oid" : "507d95d5719dbef170f15bfa" }, "name" : "AC3 Case Green", "type" : [ "accessory", "case" ], "color" : "green", "price" : 12, "rating" : 1,"warranty_years" : 0 }
{ "_id" : { "$oid" : "507d95d5719dbef170f15bfb" }, "name" : "Phone Extended Warranty", "type" : "warranty", "price" : 38, "rating" : 5,"warranty_years" : 2, "for" : [ "ac3", "ac7", "ac9", "qp7", "qp8", "qp9" ] }
命令:mongoexport -d dbname -c collectionname -o filepath --type json/csv -f field
示例:mongoexport -d test_db -products -o pro.json
查看有那些数据库show dbs
获取当前数据库的名称
创建数据库use db name
创建一个Collections Document
db.cool_new_stff.insertOne()db.cool.new.stff.insertOne()
show dbs
admin 180.00 KiB
config 72.00 KiB
local 72.00 KiB
test_db 232.00 KiB
show databases
admin 180.00 KiB
config 72.00 KiB
local 72.00 KiB
test_db 232.00 KiB
use example
'switched to db example'
doc = {"title":"A","desc":"demo"}
{ title: 'A', desc: 'demo' }
db.name.insertOne(doc);
{ acknowledged: true,
insertedId: ObjectId("6357ed0001c87366b1808a96") }
db.name.insertOne(doc);
{ acknowledged: true,
insertedId: ObjectId("6357ed0001c87366b1808a96") }
db.cool_new_stff.insertOne({});
{ acknowledged: true,
insertedId: ObjectId("6357ee6601c87366b1808a97") }
db.cool.new.stff.insertOne({});
{ acknowledged: true,
insertedId: ObjectId("6357ee7f01c87366b1808a98") }
show collections
cool_new_stff
cool.new.stff
name
查找所有:db.products.find()
查找类型等于’service’的:db.products.find({“type”:“service”});
格式化显示:db.products.find({“type”:“service”}).pretty();
只展示type该字段:db.products.find({),{“type”:1});
db.products.find({“type”:“service”),{“type”:1}).pretty();
支持正则表达式
db.products.find({“name”:{$regex:/phone/i}})
db.products.find({“name”:{Sregex:/phone/i)),{“type”:1))
db.name.find()
{ _id: ObjectId("6357ed0001c87366b1808a96"), title: 'A', desc: 'demo' }
{ _id: ObjectId("6357f15101c87366b1808a9c"), type: 123 }
{ _id: ObjectId("6357f17e01c87366b1808a9e"), name: 'Huathy' }
db.name.find({"type":"1"})
db.name.find({"type":1})
db.name.find({"type":123})
{ _id: ObjectId("6357f15101c87366b1808a9c"), type: 123 }
db.name.find({"title":"A"}).count()
4
db.name.find({"title":"A"}).limit(2)
{ _id: ObjectId("6357ed0001c87366b1808a96"),
title: 'A',
desc: 'demo' }
{ _id: ObjectId("6357f13001c87366b1808a99"),
title: 'A',
desc: 'demo' }
注意:skip()对于count()无效。也就是说不论是否跳过,统计总数都不变。
db.names.find()
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
{ _id: ObjectId("635940002108eeaab632e0d9"), num: 22 }
{ _id: ObjectId("635940032108eeaab632e0da"), num: 33 }
db.names.find().sort({"num":1})
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
{ _id: ObjectId("635940002108eeaab632e0d9"), num: 22 }
{ _id: ObjectId("635940032108eeaab632e0da"), num: 33 }
db.names.find().sort({"num":-1})
{ _id: ObjectId("635940032108eeaab632e0da"), num: 33 }
{ _id: ObjectId("635940002108eeaab632e0d9"), num: 22 }
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
db.names.find().sort({"num":-1}).skip(2)
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
$gt
与 $lt
注意:大于小于比较的前提是有该字段,如果没有这个字段的记录,则不会被查询出来。(这里建议设置collections的标准)
db.names.find()
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
{ _id: ObjectId("635940002108eeaab632e0d9"), num: 22 }
{ _id: ObjectId("635940032108eeaab632e0da"), num: 33 }
{ _id: ObjectId("635940082108eeaab632e0db"), num: 44 }
{ _id: ObjectId("6359400c2108eeaab632e0dc"), num: 55 }
{ _id: ObjectId("635942d72108eeaab632e0dd"), name: 'Huathy' }
db.names.find({"num":{$gt:33}})
{ _id: ObjectId("635940082108eeaab632e0db"), num: 44 }
{ _id: ObjectId("6359400c2108eeaab632e0dc"), num: 55 }
db.names.find({"num":{$lt:33}})
{ _id: ObjectId("63593ffb2108eeaab632e0d8"), num: 11 }
{ _id: ObjectId("635940002108eeaab632e0d9"), num: 22 }
$or
(或)、$and
(并)、$all
(全)、$in
(有)$or
(或)、$and
(并)db.prod.find({$or:[{"price":{$lt:100}},{"rating":{$gt:3}}]});
{ _id: ObjectId("63594a882108eeaab632e0de"),
price: 55,
rating: 1 }
{ _id: ObjectId("63594a8c2108eeaab632e0df"),
price: 55,
rating: 2 }
{ _id: ObjectId("63594a902108eeaab632e0e0"),
price: 55,
rating: 3 }
{ _id: ObjectId("63594aa02108eeaab632e0e2"),
price: 205,
rating: 4 }
db.prod.find({$and:[{"price":{$lt:100}},{"rating":{$gt:2}}]});
{ _id: ObjectId("63594a902108eeaab632e0e0"),
price: 55,
rating: 3 }
db.prod.find({$and:[{"price":{$lt:100}},{"rating":{$gt:2}}]}).count();
1
$all
(全)、$in
(有)-- 所有都要满足
db.prod.find({"price":{$all:[55,100]}});
{ _id: ObjectId("635c000507b9962cd04d608f"),
price: [ 55, 100 ] }
-- 满足条件之一即可
db.prod.find({"price":{$in:[55,105]}});
{ _id: ObjectId("63594a882108eeaab632e0de"),
price: 55,
rating: 1 }
{ _id: ObjectId("63594a962108eeaab632e0e1"),
price: 105,
rating: 3 }
{ _id: ObjectId("635c000507b9962cd04d608f"),
price: [ 55, 100 ] }
update修改所有;updateOne修改一个
$set
修改db.prod.find()
{ _id: ObjectId("63594aa02108eeaab632e0e2"),
price: 205,
rating: 4 }
-- 条件属性和值 设置 修改的属性和值
db.prod.updateOne({"rating":4},{$set:{"price":100}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
db.prod.find()
{ _id: ObjectId("63594aa02108eeaab632e0e2"),
price: 100,
rating: 4 }
$unset
删除字段db.prod.updateOne({"rating":4},{$unset:{"price":1}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
db.prod.find()
{ _id: ObjectId("63594aa02108eeaab632e0e2"), rating: 4 }
$inc
增加db.prod.updateOne({"rating":4},{$inc:{"price":1000}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
db.prod.find()
{ _id: ObjectId("63594aa02108eeaab632e0e2"),
rating: 4,
price: 1000 }
-- 如果再次执行操作,则会再次增加
db.prod.updateOne({"rating":4},{$inc:{"price":1000}})
db.prod.find()
{ _id: ObjectId("63594aa02108eeaab632e0e2"),
rating: 4,
price: 2000 }
$push $pull
增加 / 移除$push
db.prod.find()
{ _id: ObjectId("635c000507b9962cd04d608f"),
price: [ 55, 100 ],
rating: 5 }
db.prod.updateOne({"rating":5},{$push:{"price":1000}})
{ acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0 }
db.prod.find()
{ _id: ObjectId("635c000507b9962cd04d608f"),
price: [ 55, 100, 1000 ],
rating: 5 }
db.prod.deleteOne({"_id":"63594a8c2108eeaab632e0df"})
{ acknowledged: true, deletedCount: 0 }
db.prod.find({"_id":"63594a8c2108eeaab632e0df"})
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
spring:
data:
mongodb:
uri: mongodb://admin:123456@172.25.196.210:27017/example?authSource=admin
@Autowired
private MongoTemplate mongoTemplate;
public class MongoTest1 extends ApplicationTests{
@Autowired
private MongoTemplate mongoTemplate;
/**
* 创建集合
*/
@Test
public void test_create(){
boolean exists = mongoTemplate.collectionExists("emp");
if(exists){
mongoTemplate.dropCollection("emp");
}
mongoTemplate.createCollection("emp");
}
}
测试:
@Test
public void test_insert() {
Employee employee = new Employee(1001, "Huathy", 20, 10000.0, new Date());
Employee emp1 = mongoTemplate.insert(employee);
System.out.println("TEST 1 ==> " + emp1.toString());
Employee emp2 = mongoTemplate.save(employee);
System.out.println("TEST 2 ==> " + emp2.toString());
List<Employee> list = Arrays.asList(
new Employee(1002, "嘻嘻", 20, 20000.0, new Date()),
new Employee(1003, "嘿嘿", 20, 30000.0, new Date())
);
Collection<Employee> coll = mongoTemplate.insert(list, Employee.class);
coll.forEach(c -> {
System.out.println("COLL INSERT ==> " + c.toString());
});
}
注意:通过SpringDataMongoDB还会给集合中增加一个class属性,存储新增时Document对应Java中类的全路径。这么做是为了查询的时候能够把Doucument转为Java类型。
Criteria是标准查询的接口。可以引用静态的Criteria.where把多个条件组合到一起,就可以轻松的将多个方法标准和查询条件相结合,方便查询语句操作。
Criteria | MongoDB | 说明 |
---|---|---|
and | $and | 并且 |
andOperator | $and | 并且 |
orOperator | $or | 或者 |
gt | $gt | 大于 |
gte | $gte | 大于等于 |
in | $in | 包含 |
is | $is | 等于 |
lt | $lt | 小于 |
lte | $lte | 小于等于 |
nin | $nin | 不包含 |
测试:
/**
* 查询与条件查询
*/
@Test
public void test_find() {
System.out.println("==============查询所有文档=================");
List<Employee> allemps = mongoTemplate.findAll(Employee.class);
List<Employee> allemps2 = mongoTemplate.find(new Query(), Employee.class);
allemps.forEach(e -> {
System.out.println(e.toString());
});
System.out.println("============根据_id查询===================");
Employee emp1 = mongoTemplate.findById(1001, Employee.class);
System.out.println("findByID ==> " + emp1.toString());
System.out.println("============findOne返回第一个文档===================");
Employee emp2 = mongoTemplate.findOne(new Query(), Employee.class);
System.out.println("findOne ==> " + emp2.toString());
System.out.println("============find 单 条件查询===================");
Query query = new Query(Criteria.where("salary").gt(6000).lte(10000));
List<Employee> emps3 = mongoTemplate.find(query, Employee.class);
emps3.forEach(e -> {
System.out.println("find ==> " + e.toString());
});
System.out.println("============find 多 条件查询===================");
Criteria criteria = new Criteria();
criteria.orOperator(Criteria.where("salary").gt(6000).lte(10000), Criteria.where("name").regex("嘻"));
List<Employee> emps4 = mongoTemplate.find(new Query(criteria), Employee.class);
emps4.forEach(e -> {
System.out.println("find ==> " + e.toString());
});
}
/**
* 排序与分页
*/
@Test
public void test_sort() {
System.out.println("============ sort ===================");
Query query = new Query();
query.with(Sort.by(Sort.Order.desc("salary")));
List<Employee> emps = mongoTemplate.find(query, Employee.class);
emps.forEach(e -> {
System.out.println("order find ==> " + e.toString());
});
System.out.println("============ page ===================");
// skip limit 分页。skip跳过记录数、limit限定返回结果数
Query query1 = new Query();
query1.with(Sort.by(Sort.Order.desc("salary"))).skip(0).limit(1);
List<Employee> emps1 = mongoTemplate.find(query1, Employee.class);
emps1.forEach(e -> {
System.out.println("limit find ==> " + e.toString());
});
}
@Test
public void test_findByJson() {
System.out.println("========等值查询=========");
String eqJson = "{name:'Huathy'}";
Query query1 = new BasicQuery(eqJson);
List<Employee> emps1 = mongoTemplate.find(query1, Employee.class);
emps1.forEach(System.out::println);
System.out.println("========多条件查询=========");
String json = "{ $or:[{age:{$gte:22}},{salary:{$gt:10000}}] }";
Query query = new BasicQuery(json);
List<Employee> emps = mongoTemplate.find(query, Employee.class);
emps.forEach(System.out::println);
}
在MongoDB中无论使用客户端API还是使用SpringData,更新返回结果一定是受影响行数。若更新后的结果与更新前的结果相同,则返回0;
测试:
@Test
public void test_update(){
Query query = new Query(Criteria.where("salary").is(10000));
List<Employee> emps = mongoTemplate.find(query, Employee.class);
System.out.println("=========== 更新前 ==========");
emps.forEach(System.out::println);
Update update = new Update();
update.set("salary",12000);
UpdateResult res1 = mongoTemplate.updateFirst(query, update, Employee.class);
System.out.println("更新成功记录数1 => " + res1);
UpdateResult res2 = mongoTemplate.updateMulti(query, update, Employee.class);
System.out.println("更新成功记录数2 => " + res2);
Query query1 = new Query(Criteria.where("salary").is(50000));
List<Employee> emps1 = mongoTemplate.find(query1, Employee.class);
emps1.forEach(System.out::println);
System.out.println("=========== 更新前 ==========");
UpdateResult res3 = mongoTemplate.upsert(query, update, Employee.class);
System.out.println("更新成功记录数3 => " + res3);
}
测试:
@Test
public void test_delete(){
// 删除所有文档 // 不如使用dorpCollection()
// mongoTemplate.remove(new Query(),Employee.class);
Query query = new Query(Criteria.where("salary").is(12000));
DeleteResult res = mongoTemplate.remove(query, Employee.class);
System.out.println("删除记录数 => " + res);
}