小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
记录MongoDB的使用相关流程,从数据库的简介到实际代码的应用.
参考资料:
1 MongoDB的概述
1 MongoDB简介
MongoDB是基于C++语言编写的基于分布式文件存储的开源数据库系统,主要是为了给WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
2 MongoDB体系
将MongoDB与关系型数据库MySQL结构对比:
| MySQL | MongoDB |
|---|---|
| database数据库 | database数据库 |
| table表 | collection集合 |
| row表的一行 | document文档 |
| column行的一列 | field文档某个属性 |
| index索引 | index索引 |
| 表连接 | 不支持跨集合查询 |
| primary key主键 | primary key |
3MongoDB数据类型
MongoDB的小存储单位就是文档(document)对象,数据在MongoDB中以BSON(Binary-JSON)文档的格式存储在磁盘上.
| 数据类型 | 说明 |
|---|---|
| String | 字符串 |
| Integer | 整型数值 |
| Boolean | 布尔值 |
| Double | 双精度浮点值 |
| Min/Max keys | 将一个值与 BSON元素的最低值和最高值相对比 |
| Array | 用于将数组或列表或多个值存储为一个键 |
| Timestamp | 时间戳 |
| Object | 用于内嵌文档 |
| Null | 用于创建空值 |
| Symbol | 符号 |
| Date | 日期时间 |
| Object ID | 对象 ID |
| Binary Data | 二进制数据 |
| Code | 代码类型 |
| Regular expression | 正则表达式类型 |
2 MongoDB的配置说明
1 Windows安装步骤
以mongodb-win32-x86_64-2008plus-ssl-4.0.12.zip为例
1 下载MongoDB软件
官网下载:
2 解压文件包
解压mongodb-win32-x86_64-2008plus-ssl-4.0.12.zip得到mongodb-win32-x86_64-2008plus-ssl-4.0.12文件目录
3 创建文件存放日志和配置文件
创建log目录和config目录.在config目录中创建配置文件mongod.conf.内容如下:
systemLog:
destination: file
# 下面地址都不能使用\反斜杠, 而要使用斜杠/
# 修改为日志log目录地址
path: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.12/log/mongod.log"
logAppend: true
net:
port: 27017
bindIp: "127.0.0.1"
storage:
# 修改成为自己数据库db地址
dbPath: "D:/mongodb-win32-x86_64-2008plus-ssl-4.0.12/data/db"
journal:
enabled: true
4 启动服务
服务端启动
进入文件bin目录,在地址栏使用cmd命令,进入黑窗口, 输入命令: mongod --config …/config/mongod.conf
客户端启动
进入文件bin目录,在地址栏使用cmd命令,进入黑窗口, 输入命令: mongo --host=127.0.0.1 --port=27017
2 MongoDB连接
代码中连接MongoDB服务的标准URI语法:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
- mongodb:// 固定格式
- username:password@ 可选,如果设置,在连接数据库服务器之后,驱动都会尝试登录这个数据库
- host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址
- portX 可选的指定端口,如果不填,默认为27017
- database 如果指定username:password@,连接并验证登录指定数据库。若不指定,默认打开 test 数据库
- ?options 连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开
| 选项 | 描述 |
|---|---|
| replicaSet=name | 验证replica set的名称。 Impliesconnect=replicaSet. |
| slaveOk=true|false | true:在connect=direct模式下,驱动会连接第一台机器,即使这台服务器不是主。在connect=replicaSet模式下,驱动会发送所有的写请求到主并且把读取操作分布在其他从服务器。 false: 在 connect=direct模式下,驱动会自动找寻主服务器. 在connect=replicaSet 模式下,驱动仅仅连接主服务器,并且所有的读写命令都连接到主服务器。 |
| safe=true|false | true: 在执行更新操作之后,驱动都会发送getLastError命令来确保更新成功。(还要参考 wtimeoutMS). false: 在每次更新之后,驱动不会发送getLastError来确保更新成功 |
| w=n | 驱动添加 { w : n } 到getLastError命令. 应用于safe=true |
| wtimeoutMS=ms | 驱动添加 { wtimeout : ms } 到 getlasterror 命令. 应用于 safe=true |
| fsync=true|false | true: 驱动添加 { fsync : true } 到 getlasterror 命令.应用于 safe=true. false: 驱动不会添加到getLastError命令中。 |
| journal=true|false | 如果设置为 true, 同步到 journal (在提交到数据库前写入到实体中). 应用于 safe=true |
| connectTimeoutMS=ms | 可以打开连接的时间 |
| socketTimeoutMS=ms | 发送和接受sockets的时间 |
3 Java中MongoDB的使用
Java和MongoDB的基本操作
package com.demo.spring.mongoDB;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.bson.Document;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import sun.net.www.content.audio.basic;
/**
* @Description:
* @Author: cf
* @Date: 2021/10/9
*/
public class TestDemo {
private MongoClientURI mongoClientURI;
private MongoClient mongoClient;
@Before
public void init() {
// 无密码模式
// mongoClientURI = new MongoClientURI("mongodb://localhost:27017/mycol");
// 有密码模式
mongoClientURI = new MongoClientURI("mongodb://cf:123456@localhost:27017/mycol");
mongoClient = new MongoClient(mongoClientURI);
System.out.println("mongoClient 对象生成");
// // 连接到 mongodb 服务
// mongoClient = new MongoClient("localhost", 27017);
}
@After
public void drop() {
mongoClient.close();
System.out.println("mongoClient 对象销毁");
}
// 正则查询
@Test
public void getByPattern() {
// 连接到 mongodb 服务
// MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
/**
* 左匹配:Pattern.compile("^王.*$", Pattern.CASE_INSENSITIVE);
* 右匹配:Pattern.compile("^.*王$", Pattern.CASE_INSENSITIVE);
* 完全匹配:Pattern.compile("^王$", Pattern.CASE_INSENSITIVE);
* 模糊匹配:Pattern.compile("^.*王.*$", Pattern.CASE_INSENSITIVE);
*/
// 正则查询:查询所有以王开头的用户姓名
Pattern pattern = Pattern.compile("^王.*$", Pattern.CASE_INSENSITIVE);
BasicDBObject searchCond = new BasicDBObject("description",
new BasicDBObject("$regex", pattern));
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 包含查询
@Test
public void getByInOrNin() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 包含查询:查询likes = 2、3、10的信息
List<Integer> searchList = new ArrayList<Integer>();
searchList.add(2);
searchList.add(3);
searchList.add(10);
BasicDBObject searchCond = new BasicDBObject("likes",
new BasicDBObject("$in", searchList));
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 统计查询
@Test
public void getByCount() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 统计查询:查看密码为likes的一共有多少人
BasicDBObject filter = new BasicDBObject("likes", 2);
long count = users.countDocuments(filter);
System.out.println(count);
}
// 排序查询
@Test
public void getByOrder() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 排序查询:排序规则:1(升序)、-1(降序)
MongoCursor<Document> cursor = users.find().sort(new BasicDBObject("likes", 1)).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 投影查询
@Test
public void getByProjection() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 投影查询:只显示_id和指定字段信息 value值无意义
MongoCursor<Document> cursor = users.find().projection(new BasicDBObject("likes", 1))
.iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 分页查询
@Test
public void getByPage() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 分页查询:跳过第一条,查询两条数据
MongoCursor<Document> cursor = users.find().skip(1).limit(2).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 类型查询
@Test
public void getByType() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
// 类型查询:查询所有用户名是字符串类型的用户信息
BasicDBObject searchCond = new BasicDBObject();
// searchCond.append("likes", new BasicDBObject("$type", "string"));
searchCond.append("likes", new BasicDBObject("$type", "int"));
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 连接查询: OR查询
@Test
public void getByORCondition() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
BasicDBList condList = new BasicDBList();
condList.add(new BasicDBObject("likes", new BasicDBObject("$gt", 50)));
condList.add(new BasicDBObject("likes", new BasicDBObject("$lt", 40)));
// 条件查询:likes小于200大于50的用户信息
BasicDBObject searchCond = new BasicDBObject();
searchCond.put("$or", condList);
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 连接查询: AND查询
@Test
public void getByANDCondition() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase articledb = mongoClient.getDatabase("mycol");
MongoCollection<Document> users = articledb.getCollection("test");
BasicDBList condList = new BasicDBList();
condList.add(new BasicDBObject("likes", new BasicDBObject("$gt", 50)));
condList.add(new BasicDBObject("likes", new BasicDBObject("$lt", 200)));
// 条件查询:likes小于200大于50的用户信息
BasicDBObject searchCond = new BasicDBObject();
searchCond.put("$and", condList);
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 条件查询 常见操作符:等于、$ne、$gte、$lte、$gt、$lt
// TODO 等于怎么表示? 直接进行比较, 不用添加操作符(如下)
@Test
public void getByCondition() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
MongoDatabase articledb = mongoClient.getDatabase("mycol");
// 如果存在users,返回users,如果不存在,创建users
MongoCollection<Document> users = articledb.getCollection("test");
// 条件查询:查询likes不等于200的用户信息
BasicDBObject searchCond = new BasicDBObject();
// 常见操作符:等于、$ne、$gte、$lte、$gt、$lt
searchCond.append("likes", new BasicDBObject("$ne", 200));
// 等于
// searchCond.append("likes", 100);
MongoCursor<Document> cursor = users.find(searchCond).iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
// 删除文档, 符合条件的第一个/符合条件的所有文档
@Test
public void deleteDocument() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
MongoCollection<Document> collection = mongoDatabase.getCollection("test");
System.out.println("集合 test 选择成功");
// deleteMany 删除多条
// deleteOne 删除一条
//删除符合条件的第一个文档
collection.deleteOne(Filters.eq("likes", 200));
//删除所有符合条件的文档
collection.deleteMany(Filters.eq("likes", 200));
//检索查看结果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
System.out.println(mongoCursor.next());
}
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 更新文档
@Test
public void updateDocument() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
MongoCollection<Document> collection = mongoDatabase.getCollection("test");
System.out.println("集合 test 选择成功");
// 如果我们只想修改文档的某个字段请使用$set操作符修改,否则其它字段都会不见了
// updateMany 修改所有符合条件的
// updateOne 修改符合条件的一条
//更新文档 将文档中likes=100的文档修改为likes=200
collection.updateMany(
Filters.eq("likes", 100), new Document("$set", new Document("likes", 200)));
//检索查看结果
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
System.out.println(mongoCursor.next());
}
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 查询文档
@Test
public void getDocument() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
MongoCollection<Document> collection = mongoDatabase.getCollection("test");
System.out.println("集合 test 选择成功");
//检索所有文档
/**
* 1. 获取迭代器FindIterable<Document>
* 2. 获取游标MongoCursor<Document>
* 3. 通过游标遍历检索出的文档集合
* */
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mongoCursor = findIterable.iterator();
while (mongoCursor.hasNext()) {
System.out.println(mongoCursor.next());
}
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 插入文档$
@Test
public void insertDocument() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
MongoCollection<Document> collection = mongoDatabase.getCollection("test");
System.out.println("集合 test 选择成功");
//插入文档
/**
* 1. 创建文档 org.bson.Document 参数为key-value的格式
* 2. 创建文档集合List<Document>
* 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>) 插入单个文档可以用 mongoCollection.insertOne(Document)
* */
Document document = new Document("title", "MongoDB").
append("description", "database").
append("likes", 100).
append("by", "Fly");
List<Document> documents = new ArrayList<Document>();
documents.add(document);
collection.insertMany(documents);
System.out.println("文档插入成功");
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 获取集合
@Test
public void getCollection() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
MongoCollection<Document> collection = mongoDatabase.getCollection("test");
System.out.println("集合 test 选择成功");
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 创建集合
@Test
public void createCollection() {
try {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
mongoDatabase.createCollection("test");
System.out.println("集合创建成功");
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 连接服务2
@Test
public void test2() {
try {
//连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址
//ServerAddress()两个参数分别为 服务器地址 和 端口
ServerAddress serverAddress = new ServerAddress("localhost", 27017);
List<ServerAddress> addrs = new ArrayList<ServerAddress>();
addrs.add(serverAddress);
//MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
MongoCredential credential = MongoCredential
.createScramSha1Credential("username", "databaseName",
"password".toCharArray());
List<MongoCredential> credentials = new ArrayList<MongoCredential>();
credentials.add(credential);
//通过连接认证获取MongoDB连接
MongoClient mongoClient = new MongoClient(addrs, credentials);
//连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("databaseName");
System.out.println("Connect to database successfully");
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
// 连接服务1
@Test
public void test1() {
// 连接到 mongodb 服务
MongoClient mongoClient = new MongoClient("localhost", 27017);
// 连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
System.out.println("Connect to database successfully");
}
}