MongoDB的简介
什么是MongoDB?
- MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。
- MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
- MongoDB的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现了类似关系数据库单表查询的绝大部分功能(可以通过聚合的方式实现多表查询),而且还支持对数据建立索引。
MongoDB使用场景的特点
1.数据量大。
2.写入操作频繁。(读写都很频繁)
3.价值较低的数据,对事务性要求不高。
安装MongoDB
1.拉取镜像
docker pull mongo:4.4
2.创建挂载的目录
mkdir /data/db
3.运行镜像开启容器。(记得打开端口)
docker run -d \
--name mongodb \
-p 27017:27017 \
--restart=always \
-v mongodb:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=sl \
-e MONGO_INITDB_ROOT_PASSWORD=123321 \
mongo:4.4
进入容器的mongodb控制台
docker exec -it mongodb mongo admin --authenticationDatabase "admin"
效果为下:
MongoDB的使用
和mysql进行对比
MongoDB的基础操作
基本操作
#查询出使用的数据库
show dbs
#选中对应的数据库
use 数据库
#插入数据(插入一个对象)
db.user.insert({id:1,name:'zhangsan'})
#查出数据库中所有表的信息
show tables
show collections
#删除表
db.user.drop()
#删除数据库(要先使用use选中该表)
db.dropDatabase()
新增操作
#使用 insert操作完成插入操作
db.test.insert({id: 01, name: "好废物", age: 19})
#使用 save操作完成插入(test表示表的名字)
db.test.insert({id: 01, name:"tolen", age:19})
#查询对应表中的数据(test表示表的名字)
db.test.find()
- _id 是集合中文档的主键,用于区分文档(记录),_id自动编入索引。(主键)
- 默认情况下,_id 字段的类型为 ObjectID,是 MongoDB 的 BSON 类型之一,如果需要,用户还可以将 _id 覆盖为 ObjectID 以外的其他内容。
- ObjectID 长度为 12 字节,由几个 2-4 字节的链组成。每个链代表并指定文档身份的具体内容。以下的值构成了完整的 12 字节组合:
-
- 一个 4 字节的值,表示自 Unix 纪元以来的秒数
- 一个 3 字节的机器标识符
- 一个 2 字节的进程 ID
- 一个 3字节的计数器,以随机值开始
更新操作
更新对应的格式为下:
db.collection.update(
<query>,
<update>,
[
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
]
)
参数说明:
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如inc...)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
#选中对应的数据库(test表示表的名字)
#第一个为参数为条件,
db.test.update({id:1}, {$set:{age:22}})
#第一个为参数, 第二个参数中没有$set,就是将其他数据删除其他数据就保留设置的新值
db.test.update({id:1}, {age:25})
#update更新的字段如果不存在则就会自动创建字段
#更新不存在的数据,默认不会新增数据
db.test.update({id:5},{$set:{name:22}})
#设置第一个参数为true就表示该update为新增
db.test.update({id:5},{$set:{name:22}}, true)
删除操作
删除对应格式为下:
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
- writeConcern :(可选)抛出异常的级别。
#通过条件删除对应的数据
db.test.remove({age:22})
#设置的第二个参数为boolean类型,如果为true表示只删除一条,为false则为全部删除
db.test.remove({age:22}, true)
#删除所有的数据
db.test.remove({})
查询操作
MongoDB 查询数据的语法格式为:db.user.find([query],[fields])
- query :可选,使用查询操作符指定查询条件
- fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
格式为下:
#通过条件查询对应的数据
db.test.find({id:1,username:1})
#查询符合条件的数据的个数
db.test.find({id:1}).count()
#age小于等于对应的值
db.test.find({age:{$lte:21}})
#age大于等于对应的值
db.test.find(age:{$gte:23})
#通过或进行判断
db.test.find({$or:[{id:1},{id:2}]})
#分页查询 Skip()跳过几条数据 limit限制查询条数
db.test.find().limit(2).skip(1)
#排序查找,通过id进行倒叙
db.test.find().sort({id:-1})
索引操作
MongoDB支持的索引。
- 单字段索引(Single Field)
-
- 支持所有数据类型中的单个字段索引
- 复合索引(Compound Index)
-
- 基于多个字段的索引,创建复合索引时要注意字段顺序与索引方向
- 多键索引(Multikey indexes)
-
- 针对属性包含数组数据的情况,MongoDB支持针对数组中每一个element创建索引。
- 全文索引(Text Index)
-
- 支持任意属性值为string或string数组元素的索引查询。
- 注意:一个集合仅支持最多一个Text Index,中文分词不理想,推荐Elasticsearch。
- 地理空间索引(Geospatial Index)
-
- 2dsphere索引,用于存储和查找球面上的点
- 2d索引,用于存储和查找平面上的点
- 哈希索引(Hashed Index)
-
- 针对属性的哈希值进行索引查询,当要使用Hashed index时,MongoDB能够自动的计算hash值,无需程序计算hash值。
- hash index仅支持等于查询,不支持范围查询。
对应的格式为下:
#单字段索引,1表示升序创建索引,-1表示降序创建索引
db.test.createIndex({"字段": 1})
#2dsphere索引
db.test.createIndex({"字段": "2dsphere"})
#查询索引
db.test.getIndexes()
#查看索引的大小
db.test.totalIndexSize()
#删除对应的索引
db.test.dropIndex("索引对应的名字")
#删除所有的索引
db.test.dropIndexes()
spring Data MongoDB(SDM)使用
1.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2.修改application.yml配置文件
spring:
application:
name: sl-express-mongodb
data:
mongodb:
host: 192.168.150.101 #mongoDB的Ip
port: 27017 #对应的端口
database: sl #选中的数据库
authentication-database: admin #认证数据库
username: sl
password: "123321"
auto-index-creation: true #自动创建索引
3.创建Entity
PersonEntity
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("sl_person") //指定表名
public class Person {
@Id // 标识为主键
private ObjectId id;
@Indexed //标识索引字段
private String name;
private int age;
/**
* 用户位置
* x: 经度,y:纬度
*/
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private GeoJsonPoint location;
//存储嵌套对象数据
private Address address;
}
addressEntity
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("sl_address") //指定表名
public class Address {
private String street;
private String city;
private String zip;
}
@Document注解表示该Entity对应在mongoDB中的表(表只是个比喻,就是document对标mysql中的表)
@Id注解表示在表中对应的Id字段(表只是个比喻,就是document对标mysql中的表)
@Indexed表示在表中的索引。
service类和实现类
service
import com.sl.mongo.entity.Person;
import java.util.List;
public interface PersonService {
/**
* 新增数据
*
* @param person 数据
*/
void savePerson(Person person);
/**
* 更新数据
*
* @param person 数据
*/
void update(Person person);
/**
* 根据名字查询用户列表
*
* @param name 用户名字
* @return 用户列表
*/
List<Person> queryPersonListByName(String name);
/**
* 分页查询用户列表
*
* @param page 页数
* @param pageSize 页面大小
* @return 用户列表
*/
List<Person> queryPersonPageList(int page, int pageSize);
/**
* 根据id删除用户
*
* @param id 主键
*/
void deleteById(String id);
}
impl
import com.sl.mongo.entity.Person;
import com.sl.mongo.service.PersonService;
import org.springframework.data.mongodb.core.MongoTemplate;
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.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class PersonServiceImpl implements PersonService {
@Resource
private MongoTemplate mongoTemplate;
@Override
public void savePerson(Person person) {
mongoTemplate.save(person);
}
@Override
public void update(Person person) {
Query query = Query.query(Criteria.where("age").is(person.getAge()));
Update update = Update.update("age", person.getAge())
.set("name", person.getName())
.set("location", person.getLocation())
.set("address", person.getAddress());
//更新数据
mongoTemplate.updateFirst(
query, update, Person.class);
}
@Override
public List<Person> queryPersonListByName(String name) {
Query query = Query.query(Criteria.where("age").is(18));
return mongoTemplate.find(query, Person.class);
}
@Override
public List<Person> queryPersonPageList(int page, int pageSize) {
//在条件中可以通过and进行拼接条件, regex()方法就是模糊查询
//方法一
Query query = Query.query(Criteria.where("name").regex("三")).skip((page - 1) * pageSize).limit(pageSize);
return mongoTemplate.find(query, Person.class);
//方法二
//索引从0开始
//PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
//Query q = new Query().with(pageRequest);
//return mongoTemplate.find(query, Person.class);
}
@Override
public void deleteById(String id) {
mongoTemplate.remove(Query.query(Criteria.where("age").is(18)), Person.class);
}
}
进行测试
import com.sl.mongo.entity.Address;
import com.sl.mongo.entity.Person;
import org.bson.types.ObjectId;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import javax.annotation.Resource;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class PersonServiceTest {
@Resource
PersonService personService;
@Test
void savePerson() {
Person person = Person.builder()
.id(ObjectId.get())
.name("张三")
.age(20)
.location(new GeoJsonPoint(116.343847, 40.060539))
.address(new Address("人民路", "上海市", "666666")).build();
this.personService.savePerson(person);
}
@Test
void update() {
Person person = Person.builder()
.id(new ObjectId("632283c08139e535c2bd7579"))
.name("张三")
.age(22) //修改数据
.location(new GeoJsonPoint(116.343847, 40.060539))
.address(new Address("人民路", "上海市", "666666")).build();
this.personService.update(person);
}
@Test
void queryPersonListByName() {
List<Person> personList = this.personService.queryPersonListByName("张三");
personList.forEach(System.out::println);
}
@Test
void queryPersonPageList() {
List<Person> personList = this.personService.queryPersonPageList(1, 10);
personList.forEach(System.out::println);
}
@Test
void deleteById() {
this.personService.deleteById("632283c08139e535c2bd7579");
}
最终完成对SDM的使用。