从前慢-Mongodb

mongoDB

在这里插入图片描述

1 MongoDB的引言

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。
旨在为WEB应用提供可扩展的高性能数据存储解决方案。  
Nosql 技术门类 redis 内存型 mongodb 文档型
MongoDB是一个介于关系数据库和非关系数据库之间的产品,
是非关系数据库当中功能最丰富,最像关系数据库的。他支持
的数据结构非常松散,是类似json的bson格式,因此可以存储
比较复杂的数据类型。Mongo最大的特点是他支持的查询语言
非常强大,其语法有点类似于面向对象的查询语言,几乎可
以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

2 MongoDB的特点

面向集合存储,易存储对象类型的数据
支持查询,以及动态查询
支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言
文件存储格式为BSON(一种JSON的扩展)
支持复制和故障恢复和分片

2.1 mongo相关术语

在一个数据库软件中可以包含多个数据仓库,在每个数据仓库
中可以包含多个数据集合 ,每个数据集合中可以包含多条文
档(具体的数据)。

database
数据库,mongoDB数据库软件中可以建立多个数据库
collection
集合,一组数据的集合,可以理解为JavaScript中的数组
document
文档,一条具体的数据,可以理解为JavaScript中的对象
field
字段,文档中的属性名称,可以理解为JavaScript中的对象属性

3 MongoDB的安装和使用

1.	下载mongoDB的安装包(最新版本3.6,只能在64位系统安装)
这里使用的4.0.21版本

在这里插入图片描述

2.	上传至linux系统中解压当前的linux系统

在这里插入图片描述

3.	将解压的文件为了方便目录进行重命名(这步可以跳过)

在这里插入图片描述

4.	进入mongodb的文件夹中查看目录

在这里插入图片描述

5.	在bin目录中存在大量mongodb使用的命令

在这里插入图片描述

6. 创建目录跟文件
# cd /usr/local/mongodb
# mkdir db
# mkdir log
7.	mongodb目录下新建一个名为mongodb.conf的配置文件,
写入如下配置内容
port=27017 #端口  
dbpath= /usr/mongodb/db #数据库存文件存放目录  
logpath= /usr/mongodb/mongodb.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=false #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次
的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB

7. 输入命令启动./mongod --config /usr/local/mongodb/mongodb.conf

在这里插入图片描述

注意:
启动时要求存放数据的目录必须存在
默认的端口号是27017 可以通过--port 指定端口启动

授权登录
在日常工作中我们不可能把数据库设置为免认证登录并暴露在公
网下,所以我们需要为数据库添加用户名和密码,具体操作如下
我们把noauth那一行,前面加上#,注释掉。
再在最后一行添加 auth = true


port=27017 #端口
dbpath= /usr/local/mongodb/db #数据库存文件存放目录
logpath= /usr/local/mongodb/log/mongodb.log #日志文件存放路径
logappend=true #使用追加的方式写日志
fork=true #以守护进程的方式运行,创建服务器进程
maxConns=100 #最大同时连接数
#noauth = true #不启用验证
journal=true #每次写入会记录一条操作日志(通过journal可以
重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近
一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
auth = true #用户认证

启动数据库,./mongod --config /usr/local/mongodb/mongodb.conf
执行以下命令
//使用admin数据库
use admin
//给admin数据库添加管理员用户名和密码,用户名和密码请自行设置
db.createUser({user:"admin",pwd:"123456",roles:["root"]})
//验证是否成功,返回1则代表成功
db.auth("admin", "123456") # 验证成功后才可以执行show dbs这些命令

//切换到要设置的数据库,以test为例
use test
//为test创建用户,用户名和密码请自行设置。
db.createUser({user: "test", pwd: "123456", roles: [{ role: "dbOwner", db: "test" }]})

4 MongoDB的shell(客户端)操作

1 进入mongo的bin目录中找到如下指令

在这里插入图片描述

2 使用如下命令连接到mongodb的服务中

在这里插入图片描述

注意:
a)	连接到mongodb后,mongo和mysql数据库有点像,先是一个一
个库的概念,操作之前需要先选中库
3 查看系统中默认的所有库 

在这里插入图片描述

4 选中一个库
a)	use  数据库名称

在这里插入图片描述

注意:
use命名 存在库使用当前库  不存在则创建当前库
5 删除一个库
db.dropDatabase();

在这里插入图片描述

注意: 选中那个库,删除的就是当前选中的库
6 Mongodb的数据库中,库中是一个一个集合的概念,选中库后要创建一个一个的集合,集合类似于传统的关系型数据库中的表
a)	显示创建集合 db.createCollection(“t_user”);

在这里插入图片描述

7	查看mongo 中当前库 
a)	db 命令显示当前库

在这里插入图片描述

8	显示当前库中的所有集合
a)	show collections;

在这里插入图片描述

9	Mongo中插入数据
a)	向集合中插入数据
db.集合名称.insert({name:'xiaohei',age:23,sex:true});
b)	向集合中插入多条数据
db.集合名称.insert([{name:'xiaohei',age:23,sex:true},...]);	
10	Mongo中的删除数据
a)	db.集合名称.remove({条件}) //删除满足条件的数据
b)	db.集合名称.remove({不加任何条件})//删除所有文档   保留空的集合
11	Mongo中的修改数据
a)	db.集合名称.update({条件},{更新内容}); 
b)	db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()}) 
--这个更新是将符合条件的全部更新成后面的文档,相当于
先删除在更新
c)	db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming"}})    
--保留原来的值修改,但是只更新符合条件的第一条数据
d)	db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true})  
---保留原来数据更新,更新符合条件的所有数据
e)	db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true,upsert:true})  
---保留原来数据更新,更新符合条件的所有数据 没有条件符合时
插入数据
f)	db.t_user.update({name:"zhangsan"},{$inc:{age:1}},{upsert:true,multi:true}) 
--在保留原始数据同时给符合条件的所有age这列的值自增指定的大小
12	删除集合
a)	db.集合名称.drop();
13	查询集合
a)	db.集合名称.find();
b)	db.集合名称.find({条件})
c)	db.集合名称.find({条件},{显示字段,name:1,age:1}) 1 显示  0  不显示    1和0 不能混合出现
d)	查询结果排序:db.集合名称.find().sort({条件name:1,age:1}), 1   升序     -1  降序
e)	分页查询:db.集合名称.find().sort({条件}).skip(起始条数).limit(显示总记录数);
f)	总条数:db.集合名称.count();|db.t_user.find({"name":"aa"}).count();
g)	模糊查询:使用正则表达式db.集合名称.find({"name":/go/})
h)	等值(==)查询
  db.user.find({name:"张三"});
db.user.find({name:{$eq:"张三"}});
i)	且 ($and) 查询
db.t_user.find({name:"zhangsan",age:12});
db.t_user.find({$and:[{name:"zhangsan"},{id:10}]}) 
j)	$or使用:
i.	
db.集合名称.find({
			$or:[
				{key:value},{age:{$gte:20}}
			]	
		});
k)	$gt大于 $gte大于等于 $lt 小于 $lte 小于等于 $eq 等于:
i.	db.集合名称.find({“age”:{“$lte”:18,”$gte”:30}})
l)	$nor查询使用
i.	db.t_user.find({$nor:[{name:"chenyn"},{age:26}]});
15.	shell非正常关闭时,下次无法连接问题解决方案:
i.	删除数据目录中的mongo.lock文件即可

5 mongo跟mysql命令常用命令对比

查询
MySQL:  SELECT * FROM user
Mongo:  db.user.find()
MySQL:   SELECT * FROM user WHERE name = "xiaoming"
Mongo:   db.user.find({name : "xiaoming"})

插入
MySQL:  INSERT INTO user (name, age) values ("xiaoming",25)
Mongo:  db.user.insert({name: "xiaoming", age : 25})

修改集合字段
MySQL:  ALTER TABLE user add email varchar(100) comment “邮箱”;
Mongo:  db.user.insert({name: "xiaoming", age: 25, email : "xiaoming@qq.com"})

删除表内容
MySQL:  DELETE * FROM user
Mongo:  db.user.remove({})

根据条件删除
MySQL:  DELETE FROM user WHERE age < 30
Mongo:   db.user.remove({‘age’ : {$lt : 30}})
其他比较符号 gt:>;gte : >= ; lt:<;lte : <= ; $ne : !=

更新
MySQL:  UPDATE user SET age = 36 WHERE name = "xiaoming"
Mongo:  db.user.update({name: "xiaoming"}, {$set : {age: 36}})

根据条件更新
MySQL:  UPDATE user SET age = age + 3 WHERE name = "xiaoming"
Mongo:  db.user.update({name:"xiaoming"}, {$inc : {age : 3}})

6 Java操作mongoDB

1. 开启远程连接   
上面那个mongodb.conf已经设置可以远程连接了
bind_ip = 0.0.0.0  #这样就可外部访问了
2.	项目中引入mongo的坐标

在这里插入图片描述

3.	使用java操作mongo
package com.yxj.test;

import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TestMongo001 {

    private MongoClient mongoClient;


    @Before
    public void before(){
        mongoClient = new MongoClient("192.168.28.136",27017);
    }


    /**
     * 获取所有集合名称
     */
    @Test
    public void testGetCollectionNames(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoIterable<String> strings = database.listCollectionNames();
        for (String name : strings) {
            System.out.println(name);
        }
    }

    /**
     * 获取指定的集合
     */

    @Test
    public void testGetCollection(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> collection = database.getCollection("t_user");
    }

    /**
     * 获取指定集合中的所有数据
     */

    @Test
    public void testGetCollectionFindAll(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> collection = database.getCollection("t_user");
        FindIterable<Document> documents = collection.find();
        for (Document document : documents) {
            System.out.println(document);
            System.out.print(document.get("name")+"===");
            System.out.print(document.get("age")+"===");
            System.out.println();
        }
    }

    /**
     * 保存一条数据
     */
    @Test
    public void testSave(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> t_user = database.getCollection("t_user");
        Document document = new Document();
        document.put("_id","1");
        document.put("name","xiaochen");
        document.put("age",23);
        document.put("bir",new Date());
        t_user.insertOne(document);
    }

    /**
     * 保存多条数据
     */
    @Test
    public void testSaveMany(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> t_user = database.getCollection("t_user");
        List<Document > list = new ArrayList<Document>();
        Document document = new Document();
        document.put("_id","3");
        document.put("name","xiaohei");
        document.put("age",23);
        document.put("bir",new Date());
        Document document1 = new Document();
        document1.put("_id","2");
        document1.put("name","xiaohei");
        document1.put("age",23);
        document1.put("bir",new Date());
        list.add(document);
        list.add(document1);
        t_user.insertMany(list);
    }


    /**
     * 删除一条数据
     */
    @Test
    public void testDelete(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> t_user = database.getCollection("t_user");
        Document document = new Document();
        document.put("_id",1);
        t_user.deleteOne(document);

    }

    /**
     * 删除多个数据
     */
    @Test
    public void testDeleteMany(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> t_user = database.getCollection("t_user");
        Document document = new Document();
        document.put("name","xiaochen");
        t_user.deleteMany(document);
    }


    /**
     * 查询总条数
     *
     */
    @Test
    public void tesCount(){
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> t_user = database.getCollection("t_user");
        System.out.println(t_user.count());
    }

    @After
    public void after(){
        mongoClient.close();
    }

}
package com.yxj.test;

import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.regex.Pattern;

public class TestMongo002 {

    private MongoClient mongoClient;
    private MongoDatabase database;
    private MongoCollection<Document> t_user;

    @Before
    public void before(){
        mongoClient = new MongoClient("192.168.28.136",27017);
        database = mongoClient.getDatabase("test");
        t_user = database.getCollection("t_user");
    }


    /**
     * 有条件的查询数据
     */
    @Test
    public void testFind(){
        Document document = new Document();
        document.put("name", "xiaohei");
        FindIterable<Document> documents = t_user.find(document);
        for (Document doc : documents) {
            System.out.println(doc);
        }
    }

    /**
     * 有条件查询展示指定的字段
     */
    @Test
    public void  testFindField(){
        Document document = new Document();
        document.put("name","xiaohei");
        Document bson = new Document();
        bson.put("_id",1);
        bson.put("name",1);
        FindIterable<Document> documents = t_user.find(document)
                .projection(bson);//
        for (Document document1 : documents) {
            System.out.println(document1);
        }
    }


    /**
     * 查询数据取值范围
     * 条件搜索$lt/ $lte / $gt / $gte /  $ne / $eq <====> < / <= / >  /  >=  /  != /==
     */
    @Test
    public void tesRange(){
        FindIterable<Document> documents = t_user.find()
                .filter(Filters.gt("age", 54))
                .filter(Filters.lte("age", 24));
        for (Document document : documents) {
            System.out.println(document);
        }
    }

    /**
     * 条件搜索OR查询$in
     * 查询id的值是2或者是3的docuemnt
     */
    @Test
    public void testIn(){
        FindIterable<Document> documents = t_user.find().filter(Filters.in("_id", new String[]{"2", "3"}));
        for (Document document : documents) {
            System.out.println(document);
        }

    }


    /**
     * 条件搜索OR查询$or
     * 查询id是1或者是name等于jiangzz的所有文档
     */
    @Test
    public void testOr(){
        Document document1 = new Document();
        document1.put("name","chenyn");
        Document document2 = new Document();
        document2.put("age",52);

        FindIterable<Document> documents = t_user.find().filter(Filters.or(document1,document2));
        for (Document document : documents) {
            System.out.println(document);
        }
    }

    /**
     * 模糊查询
     */
    @Test
    public void testQueryLike(){
        Document document =  new Document();
        document.put("name", Pattern.compile("n",Pattern.CASE_INSENSITIVE));
        FindIterable<Document> documents = t_user.find(document);
        for (Document document1 : documents) {
            System.out.println(document1);
        }

    }


    /**
     * null值得处理
     */

    @Test
    public void testNull(){
        Document document = new Document();
        document.put("name",null);
        FindIterable<Document> documents = t_user.find(document);
        for (Document document1 : documents) {
            System.out.println(document1);
        }
    }

    /**
     *查询数组 查询地址中是北京 上海  广州的记录
     */
    @Test
    public void testAll(){
        FindIterable<Document> address = t_user.find().filter(Filters.all("address", new String[]{"beijing"}));
        for (Document document : address) {
            System.out.println(document);
        }
    }
    /**
     *查询数组 查询地址中包含 河北 的document
     */
    @Test
    public void testArray(){
        Document document1 = new Document();
        document1.put("address","hebei");
        FindIterable<Document> address = t_user.find(document1);
        for (Document document : address) {
            System.out.println(document);
        }
    }


    /**
     * 对查询结果进行排序
     */
    @Test
    public void testSort(){
        FindIterable<Document> documents = t_user.find().sort(new Document("age", -1));
        for (Document document : documents) {
            System.out.println(document);
        }
    }


    /**
     * 对查询结果进行排序 分页查询
     */
    @Test
    public void testPage(){
        FindIterable<Document> documents = t_user.find().sort(new Document("age", -1)).skip(0).limit(2);
        for (Document document : documents) {
            System.out.println(document);
        }
    }






    @After
    public void after(){
        mongoClient.close();
    }






}
package com.yxj.test;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.UUID;

public class TestMongo003 {

    private MongoClient mongoClient;
    private MongoDatabase database;
    private MongoCollection<Document> t_user;

    @Before
    public void before(){
        mongoClient = new MongoClient("192.168.28.136",27017);
        database = mongoClient.getDatabase("test");
        t_user = database.getCollection("t_user");
    }

    /**
     * 批量插入
     */
    @Test
    public void testInstert(){
        for (int i = 0; i < 100; i++) {
            Document document = new Document();
            document.put("_id", UUID.randomUUID().toString());
            document.put("name", "chenyn" + i);
            document.put("age",i);
            t_user.insertOne(document);
        }
    }


    /**
     * 删除
     */
    @Test
    public void testDelete(){
        t_user.deleteMany(Filters.gt("age",23));
    }



    /**
     * 更新
     */
    @Test
    public void testUpdate(){
        Bson filters = Filters.eq("age", 12);
        t_user.updateOne(filters,new Document("$set",new Document("name","aa")));
    }

    @After
    public void after(){
        mongoClient.close();
    }






}

7 Spring Boot整合mongoDB

1.pom配置
pom包里面添加spring-boot-starter-data-mongodb包引用
2.在application.properties中添加配置
spring.data.mongodb.uri=mongodb://192.168.42.136:27017/test

在这里插入图片描述

package com.entity;

import java.util.Date;

import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Document(collection="t_order")
public class Order {
	@Id
	@Indexed
	private ObjectId id;
	@Field("order_num")
	private String orderNum;
	private Date createDate;
	// 映射忽略的字段,该字段不会保存到mongodb。
	@Transient
	private String cc;
	
	public ObjectId getId() {
		return id;
	}
	public void setId(ObjectId id) {
		this.id = id;
	}
	public String getOrderNum() {
		return orderNum;
	}
	public void setOrderNum(String orderNum) {
		this.orderNum = orderNum;
	}
	public Date getCreateDate() {
		return createDate;
	}
	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}
	public Order(ObjectId id, String orderNum, Date createDate) {
		super();
		this.id = id;
		this.orderNum = orderNum;
		this.createDate = createDate;
	}
	public Order() {
		super();
	}
	@Override
	public String toString() {
		return "Order [id=" + id + ", orderNum=" + orderNum + ", createDate="
				+ createDate + "]";
	}
	
}

package com.entity;

import java.util.List;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection="t_person")
public class Person {
	@Id // 主键类型只能为:String,ObjectId,BigInteger
	private String id;
	private String name;
	private int age;
	private double salary;
	@DBRef
	private List<Order> orders = null;
	
	public List<Order> getOrders() {
		return orders;
	}
	public void setOrders(List<Order> orders) {
		this.orders = orders;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public Person(String id, String name, int age, double salary) {
		
		this.id = id;
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	public Person() {
		
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age
				+ ", salary=" + salary + "]";
	}
	
}

package mongotest;

import com.baizhi.entity.Order;
import com.baizhi.entity.Person;
import com.mongodb.Mongo;
import org.bson.types.ObjectId;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TestMain01 {
	
	@Autowired
	private MongoTemplate temp;
	
	
	@Test
	public void test09(){
		Person person = temp.findById("1111111111",Person.class);
		System.out.println(person.getOrders());
	}
	// 根据主键id查询
	@Test
	public void test08(){
		Person person = temp.findById("1111111111",Person.class);
		System.out.println(person.getOrders());
	}
	// 测试有级联关系的两个对象
	@Test
	public void test06(){
		Person p = new Person("1111111111","haha",23,1111);
		List<Order> list =new ArrayList<Order>();
		for(int i = 0 ; i < 3; i++){
			ObjectId objectId  = new ObjectId(new Date());
			Order o = new Order(objectId, 111111+"_"+i, new Date());
			temp.save(o);
			list.add(o);
		}
		p.setOrders(list);
		temp.save(p);
	}
	// 删除数据
	@Test
	public void test05(){
		Person s = new Person();
		s.setId(1+"");
		temp.remove(s);
	}
	// 查询person表中的所有数据
	@Test
	public void test03(){
		List<Person> list = temp.findAll(Person.class);
		for (Person s : list) {
			System.out.println(s);
		}
	}
	// 添加数据
	@Test
	public void test02() {
		/*for(int i = 0 ;  i< 5;i++){
			Student s = new Student(10+i+"", "zhangsan"+i, 12*i, 2000+i);
			temp.save(s);
		}*/
		// 主键如果存在,进行更新
		/*Student s = new Student("2", "zhangsasssssn", 111, 2000);
		temp.save(s);*/
		/**
		 * insert方法:如果key存在,报错
		 */
		Person s = new Person("2", "aa", 111, 2000);
		temp.insert(s);
	}
	// 查询所有的库
	@Test
	public void test01() {
		Mongo mongo = ac.getBean("mongo1",Mongo.class);
		List<String> list = mongo.getDatabaseNames();
		for (String dbName : list) {
			System.out.println(dbName);
		}
		
	}
}

package mongotest;

import com.baizhi.entity.Person;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicUpdate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.Update.Position;

import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;

public class TestMain02 {
	
	@Autowired
	private MongoTemplate temp;
	
	
	@Test
	public void testAddBatch(){
		for(int i = 0 ; i<10;i++){
			String id = UUID.randomUUID().toString().replace("-", "");
			Person p = new Person(id, "zhangsan"+i, 10+i*2, 10000+i*2);
			temp.save(p);
		}
	}

	@Test  //   排序
	public void testOrder(){
		Query query = new 	Query();
		query.addCriteria(new Criteria().where("age").gt(10));
		query.limit(10);
		query.skip(2);
		// 按照salary的升序排列
//		query.with(new Sort(Direction.ASC,"salary"));
		// 按照salary的降序排列
		query.with(new Sort(Direction.DESC, "salary"));
		List<Person> list = temp.find(query, Person.class);
		
		bianli(list);
	}
	@Test  
	public void testLimitSkip(){
		Query query = new 	Query();
		query.addCriteria(new Criteria().where("age").gt(10));
		query.limit(10);
		query.skip(2);
		List<Person> list = temp.find(query, Person.class);
		bianli(list);
	}
	@Test  // 查询与数组相关的信息
	public void testQuery03(){
		Query query = new 	Query();
		Pattern pattern = Pattern.compile("^.*1.*$", Pattern.CASE_INSENSITIVE);

		query.addCriteria(Criteria.where("name").regex(pattern));
		List<Person> list = temp.find(query, Person.class);
		bianli(list);
	}
	@Test  // 查询与数组相关的信息
	public void testQuery02(){
		Query query = new 	Query();
		// 查询  age数组长度为4的数据
//		query.addCriteria(Criteria.where("age").size(4));
		// 查询 age数组第三位 为 "aa"的记录
//		query.addCriteria(Criteria.where("age.2").is("aa"));
		List<Person> list = temp.find(query, Person.class);
		bianli(list);
	}
	@Test
	public void testQuery01(){
		Query query = new 	Query();
		// 查询  age =18
		//query.addCriteria(new Criteria().where("age").is(18));
		//查询 age > 12 并且  age< 20
		//query.addCriteria(new Criteria().andOperator(new Criteria("age").gt(12),new Criteria("age").lt(20)));
		//查询  age =1  或者 age = 100
//		query.addCriteria(new Criteria().orOperator(new Criteria("age").is(1),new Criteria("age").is(1000)));
		// 查询  age  in  (1,2)
//		query.addCriteria(new Criteria().where("age").in(1,2));
		
		// 查询  age值  除以5  余数为2的数据
		query.addCriteria(new Criteria("age").mod(5,2));
		List<Person> list = temp.find(query, Person.class);
		bianli(list);
	}
	public void bianli(List<Person> list){
		for (Object o : list) {
			System.out.println(o);
		}
	}
	@Test
	public void testUpdate04(){
		Query query = new 	Query();
		query.addCriteria(new Criteria().where("key1").is("hello 1"));
		Update update = new Update();
		update.set("key1", "value1");
		update.pushAll("age",new Object[]{12,"aa",13});
		temp.updateFirst(query,update, Person.class);
	}
	@Test
	public void testUpdate03(){
		Query query = new 	Query();
		query.addCriteria(new Criteria("age").gt(26).lt(30));
		// 用新元素替换旧元素
		DBObject obj = new BasicDBObject("key1", "value1");
		Update update = new BasicUpdate(obj);
		temp.updateFirst(query,update, Person.class);
	}
	@Test
	public void testUpdate02(){
		Query query = new 	Query();
		query.addCriteria(new Criteria("age").gt(26).lt(30));
		// 用新元素替换旧元素
		DBObject obj = new BasicDBObject("key1", "value1");
		Update update = new BasicUpdate(obj);
		temp.updateFirst(query,update, Person.class);
	}
	@Test
	public void testUpdate01(){
		Query query = new 	Query();
		query.addCriteria(new Criteria("age").gt(26).lt(30));
		// 在原始旧数据的基础上进行修改
		Update update = new Update();
		update.set("name","helloe zhangsan"); //根据key,对对应的值进行更新
		update.inc("salary", 3);  // 将该key对于的值进行递增
		update.pull("optKey",new String[]{"optionValue1","optionValue2"});//只对数组有效。 将新数据压入到key对应的数组中
		update.pop("optKey", Position.FIRST); // 只能对数组有用。将数组特定位置的元素移除
		
		temp.updateFirst(query,update, Person.class);
	}
	
}

8 MongoDB中的索引

索引就是为了加速查询的,MongoDB的索引几乎与传统的关
系型数据库一模一样,这其中也包括一些基本的优化技巧。
下面是创建索引的命令:
1.	创建索引:db.集合名称.ensureIndex({"name":1}) 
a)	1 代表索引升序存储  -1 代表索引降序存储
b)	_id 默认自动创建索引
2.	创建索引指定索引名称:db.集合名称.ensureIndex({"name":1},{name:"name_index"}) 
3.	查看索引是否创建成功:db.集合名称.getIndexes()
4.	删除索引的命令:db.集合名称.dropIndex({"name":1});
5.	创建复合索引:db.集合名称.ensureIndex({"name":1, "age":-1,bir:1})
a)	注意: 
i.	该索引被创建后,基于name和age的查询将会用到该索引
ii.	或者是基于name的查询也会用到该索引
iii.	但是只是基于age的查询将不会用到该复合索引。
b)	总结: 
i.	如果想用到复合索引,必须在查询条件中包含复合索引中的前N个
索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序
不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使
复合索引可以为查询所用。

ii.	如:db.t_user.find({"age": 30, "name": "stephen"})
对于上面示例中的查询条件,MongoDB在检索之前将会
动态的调整查询条件文档的顺序,以使该查询可以用到刚
刚创建的复合索引。

6.	创建唯一索引:db.t_user.ensureIndex({"name":1},{"unique":true})
注意: 在缺省情况下创建的索引均不是唯一索引。一旦创建唯一索引, 
如果再次插入name重复的文档时,MongoDB将报错,以提示插入重
复键 (exception: E11000 duplicate key error index: zpark.t_user.$name_1 dup key: { : \"xiaohei\" })
7.	重建索引:db.集合名称.reIndex(); 

9 mongoDB中的主从复制(4.0版本废弃)

主从复制是mongoDB最常用的复制方式,这种方式非常灵活,可用
于备份,故障恢复和扩展等.因为已经废弃,所以这里不展开

10 MongoDB中的副本集

MongoDB 副本集(Replica Set)是有自动故障恢复功能的
主从集群,有一个Primary节点和一个或多个Secondary节点组
成。主从集群和副本集之间最明显的区别就是副本集没有固
定的”主节点”,
整个集群会选举一个主节点,当主节点不能工作时自动变更到其他节点.
1 配置三个文件
mongodb27017.conf 

port=27017 #端口  
dbpath=/usr/local/mongodb/data/db27017  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/mongodb27017.log #日志文件存放路径  
#logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证
#auth=true  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
replSet=rs  # 副本集名称

mongodb27018.conf 

port=27018 #端口  
dbpath=/usr/local/mongodb/data/db27018  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/mongodb27018.log #日志文件存放路径  
#logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证
#auth=true  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
replSet=rs

mongodb27019.conf 

port=27019 #端口  
dbpath=/usr/local/mongodb/data/db27019  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/mongodb27019.log #日志文件存放路径  
#logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证
#auth=true  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的MongoDB
replSet=rs


2. 创建目录
dbpath=/usr/local/mongodb/data/db27017 # 没有db27017目录则启动不起来
dbpath=/usr/local/mongodb/data/db27018  # 没有db27018目录则启动不起来
dbpath=/usr/local/mongodb/data/db27019 # 没有db27019目录则启动不起来
logpath=/usr/local/mongodb/log/  # 创建log目录
3. 启动服务
./mongod --config /usr/local/mongodb/mongodb27017.conf
./mongod --config /usr/local/mongodb/mongodb27018.conf
./mongod --config /usr/local/mongodb/mongodb27019.conf

4.  连接任意一台mongo
i.	use admin
ii.	执行如下命令 # 我是在一台机器上进行的,所以ip地址一样。如果不同,修改ip即可
	var config = { 
	 	_id:"rs", 
	 	members:[
	   	{_id:0,host:"192.168.42.136:27017"},
	   	{_id:1,host:"192.168.42.136:27018"},
	   	{_id:2,host:"192.168.42.136:27019"}]
	 }
	 
iii.	rs.initiate(config);//初始化配置

c)	设置客户端临时访问数据:rs.secondaryOk();  # 得执行这个命令,否则从节点不能访问数据

11 SpringBoot操作MongoDB中的副本集

spring.data.mongodb.uri=mongodb://192.168.42.136.1:27017,192.168.42.136:27018,192.168.42.136:27019/ems?replcaSet=rs(副本集名称)

12 Mongodb中的分片

1.	分片(sharding)
分片目的是通过分片能够增加更多机器来应对不断的增加负载和数
据,还不影响应用.
分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时
也用分区(partitioning)来表示这个概念,将数据分散在不同的机器
上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载.
MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动
切分数据做负载均衡.MongoDB分片的基本思想就是将集合拆分成
多个块,这些快分散在若干个片里,每个片只负责总数据的一部
分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数
据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这
个路由器知道所有的数据存放位置,应用只需要直接与mongos
交互即可,mongos自动将请求转到相应的片上获取数据.从应
用角度看分不分片没有什么区别.

2.	什么时候分片
a)	机器磁盘不够用了
b)	单个的mongo已经不能满足写数据的性能需要了
3.mongoDB的分片架构图

在这里插入图片描述
在这里插入图片描述

4.	片键
设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依
据,这个片键称之为(shard key)
注意: 在真正的生产环境中,片键的选取很重要,片键的选取要一定要
数据散列均匀

5.	搭建分片集群(我采用的是伪分布式,也就是在一台机器上运行)
a)	分片结构的端口如下
s1-Shard Server 1:27017
s2-Shard Server 2:27018
s3-Shard Server 3:27019
s4-Shard Server 4:27020
s5-Config Server5 :27021
s6-Config Server6 :27022
s7-Config Server7 :27023
s8-Route Process8:27024
b)	创建数据目录
/usr/local/mongodb/data/27017         
/usr/local/mongodb/data/27018
/usr/local/mongodb/data/27019
/usr/local/mongodb/data/27020
/usr/local/mongodb/data/27021
/usr/local/mongodb/data/27022
/usr/local/mongodb/data/27023
c) 创建片键服务器配置文件
/usr/local/mongodb/config/s1.conf

port=27017 #端口  
dbpath=/usr/local/mongodb/data/27017  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s1.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
shardsvr=true

/usr/local/mongodb/config/s2.conf

port=27018 #端口  
dbpath=/usr/local/mongodb/data/27018  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s2.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
shardsvr=true

/usr/local/mongodb/config/s3.conf

port=27019 #端口  
dbpath=/usr/local/mongodb/data/27019  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s3.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
shardsvr=true

/usr/local/mongodb/config/s4.conf

port=27020 #端口  
dbpath=/usr/local/mongodb/data/27020  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s4.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
shardsvr=true

d)创建Config Server配置文件
/usr/local/mongodb/config/s5.conf
port=27021 #端口  
dbpath=/usr/local/mongodb/data/27021  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s5.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
configsvr=true
replSet=config #  config为上面的副本集名称

/usr/local/mongodb/config/s6.conf

port=27022 #端口  
dbpath=/usr/local/mongodb/data/27022  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s6.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
configsvr=true
replSet=config

/usr/local/mongodb/config/s7.conf

port=27023 #端口  
dbpath=/usr/local/mongodb/data/27023  #数据库存文件存放目录  
logpath=/usr/local/mongodb/log/s7.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
journal=true #每次写入会记录一条操作日志(通过journal可以重新构造出写入的数据)。
#即使宕机,启动时wiredtiger会先将数据恢复到最近一次的checkpoint点,然后重放后续的journal日志来恢复。
storageEngine=wiredTiger  #存储引擎有mmapv1、wiretiger、mongorocks
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
configsvr=true
replSet=config

e) 创建路由配置信息
s8.conf

port=27024 #端口  
logpath=/usr/local/mongodb/log/s8.log #日志文件存放路径  
logappend=true #使用追加的方式写日志  
fork=true #不以守护程序的方式启用,即不在后台运行  
maxConns=100 #最大同时连接数  
noauth=true #不启用验证  
bind_ip = 0.0.0.0  #这样就可外部访问了,例如从win10中去连虚拟机中的
configdb=config/192.168.42.136:27021,192.168.42.136:27022,192.168.42.136:27023

f) 创建日志目录
/usr/local/mongodb/log

g) 启动片键服务器
./mongod --config /usr/local/mongodb/config/s1.conf
./mongod --config /usr/local/mongodb/config/s2.conf
./mongod --config /usr/local/mongodb/config/s3.conf
./mongod --config /usr/local/mongodb/config/s4.conf
h) 启动config服务器
/mongod --config /usr/local/mongodb/config/s5.conf
/mongod --config /usr/local/mongodb/config/s6.conf
/mongod --config /usr/local/mongodb/config/s7.conf

i)	初始化config的配置服务器副本集
i.	登录任意config的server节点中使用 use admin 
ii.	在admin中执行
var config = { 
	 	_id:"config",
		configsvr:true, 
	 	members:[
	   	{_id:0,host:"192.168.42.136:27021"},
	   	{_id:1,host:"192.168.42.136:27022"},
	   	{_id:2,host:"192.168.42.136:27023"}]
	 }
iii.初始化副本集配置 rs.initiate(config);

j) 启动路由
./mongos --config /usr/local/mongodb/config/s8.conf 

h)客户端登陆到mongos中 mongo --port 27024
i.	use admin
ii.	添加分片节点: 
db.runCommand({ addshard:"192.168.42.136:27017","allowLocal":true });
db.runCommand({ addshard:"192.168.42.136:27018","allowLocal":true });
db.runCommand({ addshard:"192.168.42.136:27019","allowLocal":true });
db.runCommand({ addshard:"192.168.42.136:27020","allowLocal":true });
iii. 设置分片的库:db.runCommand({ enablesharding:"yxj" });
iiii. 设置那个库中哪个集合以及片键信息:
db.runCommand({ shardcollection: "yxj.users", key: { _id:1}})  # 对yxj库的users表的id字段进行分片。如果这个yxj库不存在。会自动创建。这个没有进行哈希处理。可能分片不均匀
db.runCommand({ shardcollection: "yxj.emps", key: { _id: "hashed"}}) # 对id进行哈希处理

i) 对库的增删查改对操作路由表即可实现

13 SpringBoot操作分片

spring.data.mongodb.uri=mongodb://192.168.42.136:27024

14 图片总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

想要获取该该课程markdown笔记(脑图+笔记)。可以扫描以下
微信公众号二维码。或者搜索微信公众号-Java大世界。回复modb
即可获取笔记获取方式。

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

unique_perfect

您的支持是我创造的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值