MongoDB简介
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
MongoDB创建删除数据库
MongoDB使用 use DATABASE_NAME
命令来创建数据库。如果指定的数据库DATABASE_NAME
不存在,则该命令将创建一个新的数据库,否则返回现有的数据库。
创建
use 命令
MongoDB使用 use DATABASE_NAME
命令来创建数据库。如果指定的数据库DATABASE_NAME
不存在,则该命令将创建一个新的数据库,否则返回现有的数据库。
语法
use DATABASE
语句的基本语法如下 -
use DATABASE_NAME
示例
如果要创建一个名称为<newdb>
的数据库,那么使用 use DATABASE
语句将如下所示:
> use newdb
switched to db newdb
要检查当前选择的数据库,请使用 db
命令 -
>db
newdb
如果要检查数据库列表,请使用命令:show dbs
。
>show dbs
local 0.000025GB
test 0.00002GB
创建的数据库(newdb
)不在列表中。要显示数据库,需要至少插入一个文档,空的数据库是不显示出来的。
>db.items.insert({"name":"yiibai tutorials"})
>show dbs
local 0.00005GB
test 0.00002GB
newdb 0.00002GB
在 MongoDB 中默认数据库是:test
。 如果您还没有创建过任何数据库,则集合/文档将存储在test
数据库中。
删除
db.dropDatabase() 方法
MongoDB中的 db.dropDatabase()
命令用于删除现有的数据库。
db.dropDatabase()
这将删除当前所选数据库。 如果没有选择任何数据库,那么它将删除默认的’test
‘数据库。
示例
首先,使用命令show dbs
检查可用数据库的列表。
>show dbs
local 0.00025GB
newdb 0.0002GB
test 0.00012GB
如果要删除新数据库<newdb>
,那么dropDatabase()
命令将如下所示:
>use newdb
switched to db newdb
>db.dropDatabase()
>{ "dropped" : "newdb", "ok" : 1 }
现在检查数据库列表,如下 -
>show dbs
local 0.00025GB
test 0.0002GB
创建集合
createCollection()方法
MongoDB 的 db.createCollection(name,options)
方法用于在MongoDB 中创建集合。
语法
createCollection()
命令的基本语法如下 -
db.createCollection(name, options)
在命令中,name
是要创建的集合的名称。 options
是一个文档,用于指定集合的配置。
参数 | 类型 | 描述 |
---|---|---|
name | String | 要创建的集合的名称 |
options | Document | (可选)指定有关内存大小和索引的选项 |
options
参数是可选的,因此只需要指定集合的名称。 以下是可以使用的选项列表:
字段 | 类型 | 描述 |
---|---|---|
capped | Boolean | (可选)如果为true ,则启用封闭的集合。上限集合是固定大小的集合,它在达到其最大大小时自动覆盖其最旧的条目。 如果指定true ,则还需要指定size 参数。 |
autoIndexId | Boolean | (可选)如果为true ,则在_id 字段上自动创建索引。默认值为false 。 |
size | 数字 | (可选)指定上限集合的最大大小(以字节为单位)。 如果capped 为true ,那么还需要指定此字段的值。 |
max | 数字 | (可选)指定上限集合中允许的最大文档数。 |
在插入文档时,MongoDB首先检查上限集合capped
字段的大小,然后检查max
字段。
例子
没有使用选项的createCollection()
方法的基本语法如下 -
>use test
switched to db test
>db.createCollection("mycollection")
{ "ok" : 1 }
可以使用命令show collections
检查创建的集合。
>show collections
mycollection
以下示例显示了createCollection()
方法的语法,其中几个重要选项 -
> db.createCollection("mycol", {capped : true, autoIndexId : true, size : 6142800, max : 10000 })
{ "ok" : 1 }
在 MongoDB 中,不需要创建集合。当插入一些文档时,MongoDB 会自动创建集合。
>db.newcollection.insert({"name" : "yiibaitutorials"})
>show collections
mycol
newcollection
mycollection
删除集合
drop()方法
MongoDB 的 db.collection.drop()
用于从数据库中删除集合。
语法
drop()
命令的基本语法如下 -
db.COLLECTION_NAME.drop()
示例
首先,检查数据库 test
中可用的集合。
>use test
switched to db test
> show collections
mycol
mycollection
newcollection
现在删除名称为 mycollection
的集合。
>db.mycollection.drop()
true
再次检查当前数据库的集合列表,如下 -
> show collections
mycol
newcollection
如果选定的集合成功删除,drop()
方法将返回true
,否则返回false
。
插入文档
insert()方法
要将数据插入到 MongoDB 集合中,需要使用 MongoDB 的 insert()
或save()
方法。
语法
insert()
命令的基本语法如下:
>db.COLLECTION_NAME.insert(document)
示例
>db.mycol.insert({
_id: 100,
title: 'MongoDB Overview',
description: 'MongoDB is no sql database',
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100,
})
这里mycol
是集合的名称,在前一章中所创建的。如果数据库中不存在集合,则MongoDB将创建此集合,然后将文档插入到该集合中。
在插入的文档中,如果不指定_id
参数,那么 MongoDB 会为此文档分配一个唯一的ObjectId。
_id
为集合中的每个文档唯一的12
个字节的十六进制数。 12
字节划分如下 -
_id: ObjectId(4 bytes timestamp, 3 bytes machine id, 2 bytes process id, 3 bytes incrementer)
要在单个查询中插入多个文档,可以在insert()
命令中传递文档数组。如下所示 -
> db.mycol.insert([
{
_id: 101,
title: 'MongoDB Guide',
description: 'MongoDB is no sql database',
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 100
},
{
_id: 102,
title: 'NoSQL Database',
description: "NoSQL database doesn't have tables",
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['mongodb', 'database', 'NoSQL'],
likes: 210,
comments: [
{
user:'user1',
message: 'My first comment',
dateCreated: new Date(2017,11,10,2,35),
like: 0
}
]
},
{
_id: 104,
title: 'Python Quick Guide',
description: "Python Quick start ",
by: 'yiibai tutorials',
url: 'http://www.yiibai.com',
tags: ['Python', 'database', 'NoSQL'],
likes: 30,
comments: [
{
user:'user1',
message: 'My first comment',
dateCreated: new Date(2018,11,10,2,35),
like: 590
}
]
}
])
要插入文档,也可以使用db.post.save(document)
。 如果不在文档中指定_id
,那么save()
方法将与insert()
方法一样自动分配ID的值。如果指定_id
,则将以save()
方法的形式替换包含_id
的文档的全部数据。
其它插入文档的方法
db.collection.insertOne()方法
db.collection.insertOne()
方法将单个文档插入到集合中。以下示例将新文档插入到库存集合中。 如果文档没有指定_id
字段,MongoDB会自动将_id
字段与ObjectId
值添加到新文档。
db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
)
db.collection.insertOne()
方法返回包含新插入的文档的`_id```字段值的文档。
执行结果如下 -
> db.inventory.insertOne(
... { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
... )
{
"acknowledged" : true,
"insertedId" : ObjectId("5955220846be576f199feb55")
}
db.collection.insertMany()方法
db.collection.insertMany()
方法将多个文档插入到集合中,可将一系列文档传递给db.collection.insertMany()
方法。以下示例将三个新文档插入到库存集合中。如果文档没有指定_id
字段,MongoDB会向每个文档添加一个ObjectId值的_id
字段。
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
{ item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
{ item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])
insertMany()
返回包含新插入的文档_id
字段值的文档。执行结果如下 -
> db.inventory.insertMany([
... { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
... { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
... { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
... ])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("59552c1c46be576f199feb56"),
ObjectId("59552c1c46be576f199feb57"),
ObjectId("59552c1c46be576f199feb58")
]
}
查询文档
find()方法
要从MongoDB集合查询数据,需要使用MongoDB的find()
方法。
语法
find()
命令的基本语法如下:
>db.COLLECTION_NAME.find(document)
find()
方法将以非结构化的方式显示所有文档。
pretty()方法
要以格式化的方式显示结果,可以使用pretty()
方法。
语法
> db.mycol.find().pretty()
示例
>db.mycol.find().pretty()
{
"_id": 100,
"title": "MongoDB Overview",
"description": "MongoDB is no sql database",
"by": "yiibai tutorials",
"url": "http://www.yiibai.com",
"tags": ["mongodb", "database", "NoSQL"],
"likes": "100"
}
除了find()
方法外,还有一个findOne()
方法,它只返回一个文档。
MongoDB 与 RDBMS的等效 Where 子句
要在一些条件的基础上查询文档,可以使用以下操作。
操作 | 语法 | 示例 | RDBMS等效语句 |
---|---|---|---|
相等 | {<key>:<value>} | db.mycol.find({"by":"yiibai"}).pretty() | where by = 'yiibai' |
小于 | {<key>:{$lt:<value>}} | db.mycol.find({"likes":{$lt:50}}).pretty() | where likes < 50 |
小于等于 | {<key>:{$lte:<value>}} | db.mycol.find({"likes":{$lte:50}}).pretty() | where likes <= 50 |
大于 | {<key>:{$gt:<value>}} | db.mycol.find({"likes":{$gt:50}}).pretty() | where likes > 50 |
大于等于 | {<key>:{$gte:<value>}} | db.mycol.find({"likes":{$gte:50}}).pretty() | where likes >= 50 |
不等于 | {<key>:{$ne:<value>}} | db.mycol.find({"likes":{$ne:50}}).pretty() | where likes != 50 |
下面我们将对上表中的所有操作演示 -
MongoDB中的AND操作符
语法
在find()
方法中,如果通过使用’,
‘将它们分开传递多个键,则 MongoDB 将其视为AND
条件。 以下是AND
的基本语法 -
>db.mycol.find(
{
$and: [
{key1: value1}, {key2:value2}
]
}
).pretty()
示例
以下示例将显示由“yiibai tutorials
”编写并且标题为“MongoDB Overview”的所有教程。
> db.mycol.find({$and:[{"by":"yiibai tutorials"},{"title": "MongoDB Overview"}]}).pretty()
{
"_id" : 100,
"title" : "MongoDB Overview",
"description" : "MongoDB is no sql database",
"by" : "yiibai tutorials",
"url" : "http://www.yiibai.com",
"tags" : [
"mongodb",
"database",
"NoSQL"
],
"likes" : 100
}
对于上面给出的例子,等效的SQL where
子句是 -
SELECT * FROM mycol where by ='yiibai tutorials' AND title ='MongoDB Overview'
可以在find
子句中传递任意数量的键值。
MongoDB中的OR操作符
语法
在要根据OR
条件查询文档,需要使用$or
关键字。 以下是OR
条件的基本语法 -
>db.mycol.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
示例
以下示例将显示由“yiibai tutorials
”编写或标题为“MongoDB Overview”的所有教程。
>db.mycol.find({$or:[{"by":"yiibai tutorials"},{"title": "MongoDB Overview"}]}).pretty()
{
"_id": 100,
"title": "MongoDB Overview",
"description": "MongoDB is no sql database",
"by": "yiibai tutorials",
"url": "http://www.yiibai.com",
"tags": ["mongodb", "database", "NoSQL"],
"likes": "100"
}
使用 AND 和 OR 条件一起
示例
以下示例将显示likes
大于10
以及标题是“MongoDB Overview
”或者“yiibai tutorials
”的所有文档。 等价SQL where子句为 -
SELECT * FROM mycol where likes> 10 AND(by ='yiibai tutorials' OR title ='MongoDB Overview')
SQL
>db.mycol.find({"likes": {$gt:10}, $or: [{"by": "yiibai tutorials"},
{"title": "MongoDB Overview"}]}).pretty()
{
"_id": 100,
"title": "MongoDB Overview",
"description": "MongoDB is no sql database",
"by": "yiibai tutorials",
"url": "http://www.yiibai.com",
"tags": ["mongodb", "database", "NoSQL"],
"likes": "100"
}
查询嵌入/嵌套文档
这里演示如何使用:db.collection.find()
方法对嵌入/嵌套文档的查询操作的示例。 此页面上的示例使用inventory
集合。要填充库存(inventory
)集合以准备一些数据,请运行以下命令:
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
匹配嵌入/嵌套文档
要在作为嵌入/嵌套文档的字段上指定相等条件,请使用查询过滤器文档{<field>:<value>}
,其中<value>
是要匹配的文档。
例如,以下查询选择字段size
等于{ h: 14, w: 21, uom: "cm" }
的所有文档:
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
整个嵌入式文档中的相等匹配需要精确匹配指定的<value>
文档,包括字段顺序。
例如,以下查询与库存(inventory
)集合中的任何文档不匹配:
db.inventory.find( { size: { w: 21, h: 14, uom: "cm" } } )
查询嵌套字段
要在嵌入/嵌套文档中的字段上指定查询条件,请使用点符号(“field.nestedField
”)。
在嵌套字段上指定等于匹配
以下示例选择在size
字段中嵌套的字段uom
等于“in
”的所有文档:
db.inventory.find( { "size.uom": "in" } )
使用查询运算符指定匹配
查询过滤器文档可以使用查询运算符来指定,如以下形式的条件:
{ <field1>: { <operator1>: <value1> }, ... }
以下查询使用size
字段中嵌入的字段h
中的小于运算符($lt
):
db.inventory.find( { "size.h": { $lt: 15 } } )
指定AND条件
以下查询选择嵌套字段h
小于15
的所有文档,嵌套字段uom
等于“in
”,status
字段等于“D
”:
db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )
更新文档
MongoDB的update()
和save()
方法用于将集合中的文档更新。update()
方法更新现有文档中的值,而save()
方法使用save()
方法中传递的文档数据替换现有文档。
MongoDB Update()方法
update()
方法更新现有文档中的值。
语法
update()
方法的基本语法如下 -
> db.COLLECTION_NAME.update(SELECTION_CRITERIA, UPDATED_DATA)
示例
考虑mycol
集合具有以下数据 -
> db.mycol.find({}, {'_id':1, 'title':1})
{ "_id" : 100, "title" : "MongoDB Overview" }
{ "_id" : 101, "title" : "MongoDB Guide" }
{ "_id" : 102, "title" : "NoSQL Database" }
{ "_id" : 104, "title" : "Python Quick Guide" }
以下示例将为标题为“MongoDB Overview
”的文档设置为“New Update MongoDB Overview
”。
> db.mycol.find({'title':'MongoDB Overview'},{'_id':1, 'title':1})
{ "_id" : 100, "title" : "MongoDB Overview" }
> # 更新操作
> db.mycol.update({'title':'MongoDB Overview'},{$set:{'title':'New Update MongoDB Overview'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> # 查询更新后的结果 -
> db.mycol.find({'_id':100},{'_id':1, 'title':1})
{ "_id" : 100, "title" : "New Update MongoDB Overview" }
默认情况下,MongoDB只会更新一个文档。要更新多个文档,需要将参数’multi
‘设置为true
。
>db.mycol.update({'title':'MongoDB Overview'},
{$set:{'title':'New Update MongoDB Overview'}},{multi:true})
MongoDB Save()方法
save()
方法使用save()
方法中传递的文档数据替换现有文档。
语法
MongoDB save()
方法的基本语法如下所示:
>db.COLLECTION_NAME.save({_id:ObjectId(),NEW_DATA})
以下示例将_id
为 100
的文档使用新的文档替换。
db.mycol.save(
{
"_id" : 100, "title":"Update By Save()Method.", "by":"biuaxia.com"
}
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
db.mycol.find({'_id':100}, {'_id':1, 'title':1})
{ "_id" : 100, "title" : "Update By Save()Method." }
删除文档
remove()方法
MongoDB中的 remove()
方法用于从集合中删除文档。 remove()
方法接受两个参数。 一个是删除条件,第二个是标志:justOne
。
- criteria - (可选)符合删除条件的集合将被删除。
- justOne - (可选)如果设置为
true
或1
,则只删除一个文档。
语法
remove()
方法的基本语法如下 -
>db.COLLECTION_NAME.remove(DELLETION_CRITTERIA)
假设mycol
集合具有以下数据。
> db.mycol.find({}, {'_id':1, 'title':1})
{ "_id" : 101, "title" : "MongoDB Guide" }
{ "_id" : 102, "title" : "NoSQL Database" }
{ "_id" : 104, "title" : "Python Quick Guide" }
{ "_id" : 100, "title" : "Update By Save()Method." }
以下示例将删除_id
为“100
”的文档。
> db.mycol.find({}, {'_id':1, 'title':1})
{ "_id" : 101, "title" : "MongoDB Guide" }
{ "_id" : 102, "title" : "NoSQL Database" }
{ "_id" : 104, "title" : "Python Quick Guide" }
{ "_id" : 100, "title" : "Update By Save()Method." }
>
> db.mycol.remove({'_id':100})
WriteResult({ "nRemoved" : 1 })
> db.mycol.find({}, {'_id':1, 'title':1})
{ "_id" : 101, "title" : "MongoDB Guide" }
{ "_id" : 102, "title" : "NoSQL Database" }
{ "_id" : 104, "title" : "Python Quick Guide" }
只删除一条文档记录
如果有多条记录,并且只想删除第一条记录,则在remove()
方法中设置justOne
参数。
>db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
删除所有文档记录
删除所有文档记录,可在remove()
方法中设置justOne
参数。
如果不指定删除条件,MongoDB 将删除集合中的所有文档。 这相当于SQL的truncate
命令。
>db.mycol.remove()
>db.mycol.find()
Java访问mongodb
原生方式对MongoDB操作
package mvc.model.test;
import com.mongodb.*;
import org.junit.Test;
import java.net.UnknownHostException;
import java.util.List;
/**
* Class Describe:
* 使用原生MongoDB的一些操作
* <p>
* MongoClient相当于建立连接
* DB相当于库对象
* DBCollection相当于集合
* DBObject相当于一行json
*
* @author biuaxia
* @date 2018/11/28
* @time 14:15
*/
public class MongoDbGetTest {
@Test
/**
* 获取库名
*/
public void test1() throws UnknownHostException {
/**
* 已过时
* Mongo mongo = new Mongo();
*/
MongoClient mongo = new MongoClient("localhost");
List<String> dbs = mongo.getDatabaseNames();
for (String db : dbs) {
System.out.println("库:" + db);
}
mongo.close();
}
@Test
/**
* 拿出MongoDB的内容
*/
public void test2() throws UnknownHostException {
MongoClient mongo = new MongoClient("localhost");
DB db = mongo.getDB("test");
/**
* 查看集合名
* db.getCollectionNames()
*/
//获取dept集合对象
DBCollection dept = db.getCollection("dept");
DBCursor cursor = dept.find();
while (cursor.hasNext()) {
//DBObject就类似于json对象
DBObject obj = cursor.next();
Object no = obj.get("no");
Object dname = obj.get("dname");
System.out.println(no + "\t" + dname);
}
mongo.close();
}
@Test
/**
* 写记录/插入数据
*/
public void test3() throws UnknownHostException {
MongoClient mongo = new MongoClient("localhost");
DB db = mongo.getDB("test");
//获取dept集合对象
DBCollection dept = db.getCollection("dept");
//插入数据
DBObject dbj = new BasicDBObject();
dbj.put("no", 2);
dbj.put("dname", "huidong");
dept.insert(dbj);
mongo.close();
}
@Test
/**
* 更新/修改数据
*/
public void test4() throws UnknownHostException {
MongoClient mongo = new MongoClient("localhost");
DB db = mongo.getDB("test");
//获取dept集合对象
DBCollection dept = db.getCollection("dept");
//更新数据
DBObject q = new BasicDBObject();
q.put("no", 4);
DBObject o = new BasicDBObject();
DBObject n = new BasicDBObject();
n.put("dname", "巴中");
o.put("$set", n);
dept.update(q, o);
mongo.close();
}
}
使用mongoTemplate操作MongoDB
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<!--配置工厂-->
<mongo:db-factory id="mongoDbFactory" dbname="java11" host="localhost" port="27017"></mongo:db-factory>
<!--配置模板-->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mongoConverter"/>
</bean>
<!--转换类型-->
<!-- 默认Mongodb类型映射 -->
<bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
<constructor-arg name="typeKey">
<null/><!-- 这里设置为空,可以把 spring data mongodb 多余保存的_class字段去掉 -->
</constructor-arg>
</bean>
<!-- 转换器:1、去掉write的_class字段 2、TimestampConverter -->
<mongo:mapping-converter id="mongoConverter" base-package="mvc.model.util"
type-mapper-ref="defaultMongoTypeMapper">
<mongo:custom-converters>
<mongo:converter>
<bean class="mvc.model.util.TimestampConverter"/>
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
</beans>
package mvc.model.test;
import mvc.model.bean.Commit;
import org.junit.Test;
import org.junit.runner.RunWith;
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.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.List;
/**
* Class Describe:
* 使用Java Spring-data-mongo操作MongoDB
*
* @author biuaxia
* @date 2018/11/28
* @time 14:58
*/
@Component
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:Spring*.xml"})
public class MongoDbTemplateTest {
@Resource
private MongoTemplate mongoTemplate;
@Test
/**
* 存放对象到MongoDB
*/
public void test1() {
Commit commit = new Commit();
commit.setCommit_Id(1);
commit.setUser_Commit("水平锤子");
commit.setUser_Commits_CreateTime(new Timestamp(System.currentTimeMillis()));
mongoTemplate.save(commit);
//如果想存到其它集合而不是commit集合,那么可以使用
mongoTemplate.save(commit, "User_commit");
}
@Test
/**
* 读取集合Commit中存放的所有对象
*/
public void test2() {
//默认查user库
List<Commit> commits = mongoTemplate.findAll(Commit.class, "User_commit");
for (Commit commit : commits) {
System.out.println(commit);
}
}
@Test
/**
* 读取集合Commit中单个满足条件的Commit对象
*/
public void test3() {
Query query = new Query(Criteria.where("commit_Id").gt(0));
List<Commit> commits = mongoTemplate.find(query, Commit.class, "User_commit");
for (Commit commit : commits) {
System.out.println(commit);
}
}
}
利用MongoDB存储性能监控数据
利用之前的AOP知识,在WatchBean中写入数据
package mvc.model.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Component
@Aspect
public class WatchBean {
@Resource
private MongoTemplate mongoTemplate;
@Around("bean(*Controller)")
public Object watch(ProceedingJoinPoint pjp) throws Throwable {
//开始计时
StopWatch watch = new StopWatch();
watch.start();
//调用Controller方法
Object obj = pjp.proceed();
//结束计时
watch.stop();
//获取目标组件类名
String className = pjp.getTarget().getClass().getName();
//获取方法名
String methodName = pjp.getSignature().getName();
System.out.println(className + "组件的" + methodName + "方法执行时间:" + watch.getTotalTimeMillis());
//将性能监控信息写入MongoDB
Map data = new HashMap();
data.put("class_name", className);
data.put("method_name", methodName);
data.put("execute_time", watch.getTotalTimeMillis());
mongoTemplate.save(data, "watch_log");
return obj;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<!--配置工厂-->
<mongo:db-factory id="mongoDbFactory" dbname="java11" host="localhost" port="27017"></mongo:db-factory>
<!--配置模板-->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mongoConverter"/>
</bean>
<!--转换类型-->
<!-- 默认Mongodb类型映射 -->
<bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
<constructor-arg name="typeKey">
<null/><!-- 这里设置为空,可以把 spring data mongodb 多余保存的_class字段去掉 -->
</constructor-arg>
</bean>
<!-- 转换器:1、去掉write的_class字段 2、TimestampConverter -->
<mongo:mapping-converter id="mongoConverter" base-package="mvc.model.util"
type-mapper-ref="defaultMongoTypeMapper">
<mongo:custom-converters>
<mongo:converter>
<bean class="mvc.model.util.TimestampConverter"/>
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
</beans>
Redis持久化机制、消息传递
Redis
支持RDB
和AOF
两种持久化机制
- RDB即快照模式,每隔固定的时间后会自动备份,文件后缀为
.rdb
,规则是900秒1次、300秒10次、60秒10000次则立即备份 - AOF即日志模式,是指所有的命令行记录以
Redis
命令请求协议的格式保存为aof
文件。
MongoDB默认采用RDB模式,如需开启日志模式则需要修改配置文件redis.conf
中的appendonly修改为yes
两种持久化机制总结
RDB持久化
RDB持久化是指用数据集快照的方式记录redis数据库的所有键值对。
两个命令:SAVE命令会阻塞主进程来完成写文件,BGSAVE命令会创建子进程来完成写文件,主进程会继续处理命令。
优点:
- 只有一个文件dump.rdb,方便持久化。
- 容灾性好,一个文件可以保存到安全的磁盘。
- 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。
- 相对于数据集大时,比AOF的启动效率更高。
缺点:
- 数据安全性低,通过配置save参数来达到定时的写快照,比如 每900 秒有1个键被修改就进行一次快照,每600秒至少有10个键被修改进行快照,每30秒有至少10000个键被修改进行记录。所以如果当服务器还在等待写快照时出现了宕机,那么将会丢失数据。
- fork子进程时可能导致服务器停机1秒,数据集太大。
AOF持久化
AOF持久化是指所有的命令行记录以redis命令请求协议的格式保存为aof文件。
优点:
- 数据安全,aof持久化可以配置appendfsync属性,有always,每进行一次命令操作就记录到aof文件中一次;everySec,就是每秒内进行一次文件的写操作;no就是不进行aof文件的写操作。
- 通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof工具解决数据一致性问题。
- AOF机制的rewrite模式,用来将过大的aof文件缩小,实现原理是将所有的set 通过一句set 命令总结,所有的SADD命令用总结为一句,这样每种命令都概括为一句来执行,就可以减少aof文件的大小了。(注意,在重写的过程中,是创建子进程来完成重写操作,主进程每个命令都会在AOF缓冲区和AOF重写缓冲区进行保存,这样旧版aof文件可以实现数据最新,当更新完后将重写缓冲区中的数据写入新的aof文件中然后就可以将新的文件替换掉旧版的文件。
缺点:
- 文件会比RDB形式的文件大。
- 数据集大的时候,比rdb启动效率低。