初学者学习Mongodb基础入门
关系型数据库和非关系型数据库
对于关系型的数据库,存储数据之前,必须先建表建库,随着数据的复杂度越来越高,所建表的数量也就越来越多
但是非关系型数据库却不需要如此复杂。
一、Mongodb简介
MongoDB 是由 C++ 语言编写,一个基于分布式文件存储的开源数据库系统,MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
二、Mongodb安装
2.1 window系统
step 1: 下载安装包
从官网上下载: https://www.mongodb.com/try/download/community
step 2:双击点击安装-----》》点击 next-----》》选择 Custom ----》》可以自定义安装路径也可以默认安装路径。----》》最后将默认compass的勾去掉。
step 3: 创建数据库文件的存放位置
在MongoDB下创建data,在data下再创建db:c:\data\db
因为启动mongodb服务之前需要必须创建数据库文件的存放文件夹,否则命令不会自动创建,而且不能启动成功。
step 4 : 启动服务
-
双击Mongoddb–》》Service —》》 4.2 —》》bin —》》mongod.exe
-
在bin目录下—输入命令—cmd----》》mongod --dbpath c:\data
stpe 5: 在浏览器上输入http://localhost:27017
连接成功!
如果安装成功,在bin目录下执行命令不成功,配置环境变量:
在path中按照配置java环境一样配置 %MONGODB_HOME%\bin
2.2 Linux系统
step1:上传----/opt/sofware
step2: 解压:tar -zvxf mongodb-linux-x86_64-amazon-4.2.7.tgz
step3 :改名字 mv mongodb-linux-x86_64-amazon-4.2.7 mongodb
step 4: 配置环境变量及配置文件:
在mongodb目录下输入:vi /etc/profile
加入:export PATH=/usr/local/mongodb/bin:$PATH
step 5: 创建:mkdir /usr/local/mongodb
step 6:MongoDB的数据存储在data目录的db目录下,但是这个目录在安装过程不会自动创建,所以你需要手动创建data目录,并在data目录中创建db目录以及日志文件
mkdir -p /data/db mkdir -p /logs
step 7 :将下载好后的mongodb下bin目录复制到设好的路径也就是/usr/local/mongodb/bin
下
将目录切换到 cd /usr/local/mongodb
复制文件 cp -r /opt/softeware/mongodb/bin/ ./
step 8: 在bin目录下创建mongodb.conf文件,是个新文件,我们要在里面填入
# 数据文件存放目录
dbpath = /data/db
# 日志文件存放目录
logpath = /logs/mongodb.log
# 端口
port = 27017
# 以守护程序的方式启用,即在后台运行
fork = true
# 需要认证。如果放开注释,就必须创建MongoDB的账号,使用账号与密码才可远程访问,第一次安装建议注释
# auth=true
# 允许远程访问,或者直接注释,127.0.0.1是只允许本地访问
bind_ip=0.0.0.0
"esc" ":" "wq" # 保存退出
step 8: 启动服务
./mongod -f mongodb.conf
step9 :进入mongodb数据库
./mongo
step 10: 查看进程: netstat -nplt
关闭mongodb服务的两种方式
杀死进程: kill -9 pid
./mongod --shutdown
三、mongodb的特点
- MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
- 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=“Sameer”,Address=“8 Gandhi Road”)来实现更快的排序。
- 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
- 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
- Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
- MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
- Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
- Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
- Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
- GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
- MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
- MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言
四、Mongodb的常用数据库命令
创建数据库 use rundo 查看当前数据库: db 查看所有的数据库: show dbs 或者 show databases 切换数据库: use db_name 删除当前数据库: db.dropDatabase()
创建数据库后查看所有数据库显示你刚创建的那个数据库没有是因为你里面没有数据
db.rundo.insert({
"name":"zhangsan"})
在查询所有的数据库就会显示你刚创建好的数据库。
五、mongodb的集合命令
如果不手动创建集合,向不存在的集合中第一次加入数据的时候,集合会被自动创建出来。
-- 创建集合
db.createCollection(name,options)
-- 查看集合
show collections
-- 删除已有集合
-- 如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。
db.Collection_name.drop()
参数说明
- name: 要创建的集合名称
- options: 可选参数, 指定有关内存大小及索引的选项
options中的参数:
字段 | 类型 | 描述 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
autoIndexId | 布尔 | 3.2 之后不再支持该参数。 (可选)如为 true,自动在 _id 字段创建索引。默认为 false。 |
size | 数值 | (可选)为固定集合指定一个最大值,以千字节计(KB)。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。
-- 创建数据库test
use test
-- 在test里创建student集合
db.createCollection("student")
db.createCollection("stu",{capped : true ,autoIndexId : true, size: 6000, max : 10 })
-- 删除已有集合
db.stu.drop();
六、mongodb常见的数据类型
- Object ID: ⽂档ID
- String: 字符串, 最常⽤, 必须是有效的UTF-8
- Boolean: 存储⼀个布尔值, true或false
- Integer: 整数可以是32位或64位, 这取决于服务器
- Double: 存储浮点值
- Arrays: 数组或列表, 多个值存储到⼀个键
- Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
- Null: 存储Null值
- Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
- Date: 存储当前⽇期或时间的UNIX时间格式
七、mongodb将数据添加到集合中(插入文档)
文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。
BSON简介
BSON是基于JSON格式,是一种计算机数据交换格式,主要被用作MongoDB数据库中的数据存储和网络传输格式。它是一种二进制表示形式,能用来表示简单数据结构、关联数组(MongoDB中称为“对象”或“文档”)以及MongoDB中的各种数据类型。
BSON特点
轻量性、可遍历性、高效性。
更快的遍历速度
操作更简易
增加了额外的数据类型
7.1 MongoDB 使用向集合中插入文档
db.COLLECTION_NAME.insert(document)
db.COLLECTION_NAME.save(document)
save()
:如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne() 或 db.collection.replaceOne() 来代替。
insert()
: 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。
-- 插入单条数据
db.student.save({name:'liunana',gander:'女',age:18})
db.student.insert({name:'zhangsan',gander:'男',age:18})
-- 插入多条数据
db.student.insert([{name:'zhangsan',gander:'男',age:18},{name:'qq',gander:'女',age:20}])
-- 将数据定义为一个变量
doc = ({name:'lisi',gander:'男',age:18})
db.student.insertOne(doc)
7.2 mongodb查询文档
db.student.find()
查询所有文档
参数
query :可选,使用查询操作符指定查询条件
projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
db.student.findOne()
只返回第一条数据
db.student.find({condition})
条件查询
db.student.find({gander:'男'})
pretty()
格式化文档
7.2.1 mongodb的查询条件与RDBMS的条件查询相比
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | {<key>:<value> } |
db.col.find({"by":"菜鸟教程"}).pretty() |
where by = '菜鸟教程' |
小于 | {<key>:{$lt:<value>}} |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
小于或等于 | {<key>:{$lte:<value>}} |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
大于 | {<key>:{$gt:<value>}} |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
大于或等于 | {<key>:{$gte:<value>}} |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
7.2.2 MongoDB AND 条件
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。
db.col.find({key1:value1, key2:value2}).pretty()
db.student.find({
'name':'zhangsan','gander':'男'})
7.3 mongodb更新文档
update()
方法后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
rundo集合中插入几条数据
db.rundo.insert([{
'_id': '1',
'title': 'java',
'desc': 'Java编程'
}, {
'_id': '2',
'title': 'php',
'desc': 'php编程'
}, , {
'_id': '3',
'title': '.net',
'desc': '.net编程'
}, {
'_id': '4',
'title': 'java',
'desc': 'java编程'
}, {
'_id': '5',
'title': 'java',
'desc': 'java编程'
}])
修改java为Java
db.rundo.update({ 'title': 'java'}, {$set:{
'title':'Java'}})
找到的第一条数据被修改。若批量修改数据,则将multi
值改为true
db.rundo.update({ 'title': 'java'}, {$set:{
'title':'Java'}},{multi:true})
7.4 mongodb删除文档
remove()函数是用来移除集合中的数据。
db.collection.remove(<query>,{justOne: <boolean>,writeConcern: <document>})
query :(可选)删除的文档的条件。
justjOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false, 则删除所有匹配条件的文档。
writeConcern :(可选)抛出异常的级别。
-- 两种写法
db.rundo.remove({
'title':'Java'},1)
db.rundo.remove({
'title':'Java'},{justjOne:true})
7.5 MongoDB 关系
MongoDB 的关系表示多个文档之间在逻辑上的相互联系。
方式:嵌入和引用
- 1:1 (1对1)
- 1: N (1对多)
- N: 1 (多对1)
- N: N (多对多)
7.6 mongodb排序
sort()
方法
-- 升序
db.student.find().sort({
key:1})
-- 降序
db.student.find().sort({
key:-1})
7.7 MongoDB 索引
createIndex()
方法
db.collection.createIndex(keys, options)
Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可
db.student.createIndex({
'title':1})
7.8MongoDB聚合
aggregate()
方法
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
表达式 | 描述 |
---|---|
$sum | 计算总和。 |
$avg | 计算平均值 |
$min | 获取集合中所有文档对应值得最小值。 |
$max | 获取集合中所有文档对应值得最大值。 |
$push | 在结果文档中插入值到一个数组中。 |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 |
$first | 根据资源文档的排序获取第一个文档数据。 |
$last | 根据资源文档的排序获取最后一个文档数据 |
db.rundo.insert([{
_id: 1,
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: 2,
title: 'NoSQL Overview',
description: 'No sql database is very fast',
by_user: 'runoob.com',
url: 'http://www.runoob.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 10
},
{
_id: 3,
title: 'Neo4j Overview',
description: 'Neo4j is no sql database',
by_user: 'Neo4j',
url: 'http://www.neo4j.com',
tags: ['neo4j', 'database', 'NoSQL'],
likes: 750
}])
-- 总和
db.rundo.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
-- 相当于关系型数据库的
select by_user, count(*) from rundo group by by_user
-- 平均值
db.rundo.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
-- 对应的关系型数据库
select by_user,avg(likes) from rundo group by by_user
-- 最小值
db.mycol.aggregate([{$group : {_id : "$by_user", min : {$min : "$likes"}}}])
-- 对应的关系型数据库
select by_user,min(likes) from rundo group by by_user
-- 最大值
db.rundo.aggregate([{$group : {_id : "$by_user", max : {$max : "$likes"}}}])
-- 对应的关系型数据库
select by_user,max(likes) from rundo group by by_user
-- 根据条件找的最后一条
db.rundo.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])
-- 根据条件找每组的第一条
db.rundo.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])
八、springboot中集成mongodb
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
连接数据库
spring:
data:
mongodb:
host: 127.0.0.1
port: 27017
# 数据库名
database: user
编写entity层
package com.xinzhi.springmon.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.Date;
/**
* @author ch
* @date 2020/7/11
*/
@Document
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
@Id
private Integer id;
private String username;
private Integer age;
private Date createTime;
private Date updateTime;
}
如果没有引入lombok插件,那么entity层的getting与setting要自己手动创建
service层
package com.xinzhi.springmon.service;
import com.xinzhi.springmon.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 java.awt.print.Book;
import java.util.Date;
import java.util.List;
/**
* @author ch
* @date 2020/7/12
*/
@Service
public class UserService {
@Autowired
private MongoTemplate mongoTemplate;
/**
* 保存
*/
public String saveUser(User user) {
user.setCreateTime(new Date());
mongoTemplate.save(user);
return "SUCCESS";
}
/**
* 获得所有用户
*/
public List<User> getAllUser() {
return mongoTemplate.findAll(User.class);
}
/**
* 通过id找
*/
public User getUserById(int id) {
/**条件*/
Query query = new Query(Criteria.where("_id").is(id));
return mongoTemplate.findOne(query, User.class);
}
/**
* 跟新用户信息
*/
public String updateUser(User user) {
Query query = new Query(Criteria.where("_id").is(user.getId()));
Update update = new Update().set("username", user.getUsername()).set("age", user.getAge()).set("updateTime", new Date());
/**upsert 更新对象不存在则去添加*/
mongoTemplate.upsert(query, update, User.class);
//updateFirst 更新查询返回结果集的第一条
// mongoTemplate.updateFirst(query, update, User.class);
/**updateMulti 更新查询返回结果集的全部*/
// mongoTemplate.updateMulti(query,update,User.class);
return "SUCCESS";
}
/**
* 根据id删除
*/
public String deleteUserById(int id) {
User user = getUserById(id);
mongoTemplate.remove(user);
return "SUCCESS";
}
}
controller层
package com.xinzhi.springmon.controll;
import com.xinzhi.springmon.entity.User;
import com.xinzhi.springmon.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author ch
* @date 2020/7/11
*/
@Controller
@ResponseBody
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/save")
public String saveUser(@RequestBody User user) {
return userService.saveUser(user);
}
@GetMapping("/getAll")
public List<User> getAll() {
return userService.getAllUser();
}
@GetMapping("/findOne")
public User getUserById(@RequestParam int id) {
return userService.getUserById(id);
}
@PostMapping("/update")
public String update(@RequestBody User user) {
return userService.updateUser(user);
}
@GetMapping("/delete")
public String delUserById(@RequestParam int id) {
return userService.deleteUserById(id);
}
}
启动PostMan后,一一测试
剩下得就不一一上传演示了。