NoSql学习
1.MongoDB
1.数据库介绍
MongoDB是C++编写的一个文档数据库(以JSON为数据模型),旨在为WEB应用提供可拓展的高性能数据存储解决方案
它是一个介于关系数据库和非关系数据库之间的产品,原则上mysql能做的它也能做
database: 数据库。
collection: 数据集合,相当于 MySQL 的 table。
document: 数据记录行,相当于 MySQL 的 row。
field: 数据域,相当于 MySQL 的 column。
index: 索引。
primary key: 主键。
1.面向集合存储:MongoDB 是面向集合的,数据以 collection 分组存储。每个 collection 在数据库中都有唯一的名称
2.模式自由:集合的概念类似 MySQL 里的表,但它不需要定义任何模式
3.结构松散:对于存储在数据库中的文档,不需要设置相同的字段,并且相同的字段不需要相同的数据类型,不同结构的文档可以存在同一个 collection 里
4.高效的二进制存储:存储在集合中的文档,是以键值对的形式存在的。键用于唯一标识一个文档,一般是 ObjectId 类型,值是以 BSON 形式存在的。BSON = Binary JSON, 是在 JSON 基础上加了一些类型及元数据描述的格式
5.支持索引:可以在任意属性上建立索引,包含内部对象。MongoDB 的索引和 MySQL 的索引基本一样,可以在指定属性上创建索引以提高查询的速度。除此之外,MongoDB 还提供创建基于地理空间的索引的能力
6.支持 mapreduce:通过分治的方式完成复杂的聚合任务
7.支持 failover:通过主从复制机制,可以实现数据备份、故障恢复、读扩展等功能。基于复制集的复制机制提供了自动故障恢复的功能,确保了集群数据不会丢失
8.支持分片:MongoDB 支持集群自动切分数据,可以使集群存储更多的数据,实现更大的负载,在数据插入和更新时,能够自动路由和存储
9.支持存储大文件:MongoDB 中 BSON 对象最大不能超过
对于大文件的存储,BSON 格式无法满足。GridFS 机制提供了一个存储大文件的机制,可以将一个大文件分割成为多个较小的文档进行存储
从目前阿里云 MongoDB云数据库上的用户看,MongoDB 的应用已经渗透到各个领域
●游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新;
•物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以MongoDB 内嵌数组的形式来存储,一次查询就能 将订单所有的变更读取出来;
•社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能;
●物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析; •视频直播,使用 MongoDB 存储用户信息、礼物信息等; • 大数据应用,使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。| 国内外知名互联网公司都在使用MongoDB
没有某个业务场景必须要使用MongoDB才能解决,但使用MongoDB通常能让你以更低的成本解决问题。如果你不清楚当前业务是否适合使用MongoDB,可以通过做几道选择题来辅助决策。
应用特征 应用不需要复杂/长事务及join支持
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以)
应用需要TB甚至 PB 级别数据存储
应用发展迅速,需要能快速水平扩展
应用要求存储的数据不丢失
应用需要99.999%高可用
应用需要大量的地理位置查询、文本查询
本人使用docker安装
docker run -d --restart=always -p 27017:27017
--name mongo
-v /home/lmy/mongodb:/data/db
--privileged=true
-e MONGO_INITDB_ROOT_USERNAME=root
-e MONGO_INITDB_ROOT_PASSWORD=root
mongo:latest mongod
--auth
MongoDB常见类型 | 说明 |
---|
Object ID | 文档ID |
String | 字符串,最常用,必须是有效的UTF-8 |
Boolean | 存储一个布尔值,true或false |
Integer | 整数可以是32位或64位,这取决于服务器 |
Double | 存储浮点值 |
Arrays | 数组(js)或列表(python),多个值存储到一个键 |
Object | 用于嵌入式的文档,即一个值为一个文档 |
Null | 存储Null值 |
Timestamp | 时间戳 |
Date | 存储当前日期或时间的UNIX时间格式 |
2.基本操作及命令
控制台使用mongo --host=127.0.0.1 --port=27017
JavaScript支持:mongo shell是基于JS语法的,interpreterVersion()查看支持的js的版本
show users
show roles
show profile
load("xxx.js")
exit | quit()
help
db.help()
db.version()
show dbs | show databases
use 数据库名
db.dropDatabase()
db.集合名.help()
show collections | show tables
db.createCollection("aaa")
db.集合名.stats()
db.集合名.drop()
db.createCollection("aaa",options)
capped 布尔类型 (可选)如果为true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
size 数值类型 (可选)为固定集合指定一个最大值(以字节计)。如果 capped为 true,也需要指定该字段。
max 数值类型 (可选)指定固定集合中包含文档的最大数量。
db.createUser({user:"admin",pwd:"admin",roles:["dbOwner"]})
read
readWrite
dbAdmin
dbOwner
userAdmin
clusterAdmin
readAnyDatabase
readWriteAnyDatabase
userAdminAnyDatabase
dbAdminAnyDatabase
root
1) 插入文档 (3.2版本之后新增了db.collection.insertOne()和db.collection.insertMany())
writeConcern 决定一个写操作落到多少个节点上才算成功。
writeConcern 的取值包括 :
0:发起写操作,不关心是否成功;
1:集群最大数据节点数 : 写操作需要被复制到指定节点数才算成功;
majority : 写操作需要被复制到大多数节点上才算成功。
writeConcern : 写入策略,默认为1,即要求确认写操作, 是不要求。
ordered : 指定是否按顺序写入,默认 true,按顺序写入。
f)load("xxx.js")js中写插入命令等也可以实现批量插入
2)查询文档
a)query:可选,使用查询操作符指定查询条件
b)projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可 (默认省略)。投影时,id 为1的时候,其他字段必须是1;id是0的时候,其他字段可以是0;如果没有_id字段约束,多个其他字段必须同为0或同为1。
c)如果查询返回的条目数量较多,mongo shell则会自动实现分批显示。
默认情况下每次只显示20条,可以输入it命令读取下一批。
db.books.find({tag:"nosql"})
db.books.find({_id:ObjectId("61caa09ee0782536660494d9")})
db.books.find({type:"travel",favCount:{$gt:60}})
SQL MQL
a = 1 {a : 1}
a <> 1 {a : ($ne : 1}}
a> 1 {a : {$gt : 1}}
a>= 1 {a : {$gte : 1}}
a < 1 {a : {$lt : 1}}
a <= 1 {a : {$Ite : 1}}
SQL MQL
a = 1 AND b=1 {a:1, b:1} 或{$and : [{a:1}, {b:1}]}
a = 1 OR b = 1 {$or : [{a : 1}, {b : 1}]}
a IS NULL {a : {$exists : false}}
a IN (1, 2, 3) {a : {$in : [1, 2, 3]}}
$lt : 存在并小于
$lte : 存在并小于等于
$gt : 存在并大于
$gte : 存在并大于等于
$ne : 不存在或存在但不等于
$in : 存在并在指定数组中
指定排序 在 MongoDB 中使用 sort() 方法对数据进行排序
db.books.find({type : "travel"}).sort({favCount : -1})
分页查询 skip用于指定跳过记录数,limit则用于限定返回结果数量。可以在执行find命令的同时指定skip、limit参数,以此实现分页的功能;limit是pageSize,skip是第几页*pageSize。
db.books.find().skip(8).limit(4)
使用正则表达式查找type包含so字符串的book
db.books.find({type:{$regex:"so"}}) 或 db.books.find({type:/so/})
3)更新文档 可以用update命令对指定的数据进行更新
query : 描述更新的查询条件;
update : 描述更新的动作及新的内容;
options : 描述更新的选项
upsert : 可选,如果不存在update的记录,是否插入新的记录。默认false,不插入
multi可选,是否按条件查询出的多条记录全部更新。 默认false,只更新找到的第一条记录
writeConcern 可选,决定一个写操作落到多少个节点上才算成功
操作符 格式 描述
$set {$set : {field : value}}
$unset {$unset : {field : 1}}
$inc {$inc : {field : value}}
$rename {$rename : {old_field_name : new_field_name}}
$push { $push : {field : value}}
$pfishall {$pushAll : {field : value_array}}
$pull {$pull : {field : value}}
$addToSet {$addToSet : {field : value}}
$pop {$pop : {field : 1}}
某个book文档被收藏了,则需要将该文档的favCount字段自增
db.books.update({_id:ObjectId("61caa09ee0782536660494d9")},{Sinc:{favCount:1}})
默认情况下,update命令只在更新第一个文档之后返回,如果需要更新多个文档,则可以使用multi选项。
将分类为“novel”的文档的增加发布时间(publishedDate)
db.books.update({type : "novel"},{$set:{publishedDate : new Date()}},{"multi":true}) multi:可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
updateOne:更新单个文档。
updateMany:更新多个文档。
replaceOne:替换单个文档。
db.books.update({title : "my book"},
{$set : {tags : ["nos q1", "mongodb"], type : "none", author : "fox"}},
{upsert : true})
nMatched、nModified都为0,表示沒有文档被匹配及更新,nUpserted=1提示执行了upsert动作
update命令中的更新描述(update)通常由操作符描述,如果更新描述中不包含任何操作符,那么MongoDB会实现 文档的replace语义
db.books.update({title : "my book"}, {justTitle : "my first book"})
findAndModify兼容了查询和修改指定文档的功能,findAndModify只能更新单个文档
db.books.findAndModify({query:{_id : ObjectId("61caa09ee07825 36660494dd") },
update : {$inc : {favCount : 1}}
})
db.books.findAndModify({query:{_id : ObjectId("61caa09ee0782536660494dd") },
update:{$inc : {favCount : 1}},
new : true
})
findoneAndUpdate : 更新单个文档并返回更新前(或更新后)的文档。
findOneAndreplace : 替换单个文档并返回替换前(或替换后)的文档
4)删除文档
remove 命令需要配合查询条件使用;
匹配查询条件的文档会被删除;
指定一个空文档条件会删除所有文档;
db.user.remove({age : 28})
db.user.remove({age : {$1t : 25}})
db.user.remove({})
db.user.remove()
remove命令会删除匹配条件的全部文档,如果希望明确限定只删除一个文档,则需要指定justOne参数
db.集合名.remove(query, justone)
db.books.remove({ type : "novel"},true)
db.books.deleteMany({})
db.books.deleteMany({ type : "novel" })
db.books.deleteOne({ type : "novel" })
remove、deleteOne等命令在删除文档后只会返回确认性的信息,如果希望获得被删除的文档,则可以使用findOneAndDelete命令
db.books.findOneAndDelete({type:"nove1"})
除了在结果中返回删除文档,findOneAndDelete命令还允许定义“删除的顺序”,即按照指定顺序删除找到的第一个文档
db.books.findoneAndDelete({type : "nove1"},{sort : {favCount : 1}})
remove、deleteOne等命令只能按默认顺序删除,利用这个特性,findOneAndDelete可以实现队列的先进先出。
db.student.count()
db.student.count({"major":"Histroy"})
db.student.aggregate([{$group:{_id:"$major","人数":{$sum:1}}}])
db.student.aggregate([{$group:{_id:"$major","学生人数":{$sum:1},"平均年龄":{$avg:"$age"}}}])
db.student.aggregate([{$group:{_id:"$sex","平均年龄":{$avg:"$age"}}}])
db.cloneDatabase(“127.0.0.1”);
db.stats();
db.version();
db.userInfo.getIndexes();
db.userInfo.totalIndexSize();
db.users.dropIndex("name_1");
db.users.dropIndexes();
分组函数 | 说明 |
---|
$sum | 计算总和,$sum:1同count表示计数 |
$avg | 计算平均值 |
$min | 获取最小值 |
$max | 获取最大值 |
$push | 在结果文档中插入值到一个数组中,相当于拼接字段 |
$first | 根据资源文档的排序获取第一个文档数据 |
$last | 根据资源文档的排序获取最后一个文档数据 |
3.进阶
MongoDB副本集默认会创建local、admin数据库,local数据库主要存储副本集的元数据,admin数据库则主要存储MongoDB的用户、角色等信息。
1.慎用local数据库
从名字可以看出,它只会在本地存储数据,即local数据库里的内容不会同步到副本集里其他节点上去;目前local数据库主要存储副本集的配置信息、oplog信息,这些信息是每个Mongod进程独有的,不需要同步到副本集种其他节点
2.慎用admin数据库
当Mongod启用auth选项时,用户需要创建数据库帐号,访问时根据帐号信息来鉴权,而数据库帐号信息就存储在admin数据库下;MongoDB将admin数据库上的意向写锁(MODE_IX)直接升级为写锁(MODE_X),也就是说admin数据库的写入操作的锁级别只能到DB级别,不支持多个collection并发写入,在写入时也不支持并发读取。如果用户在admin数据库里存储业务数据,则可能遭遇性能问题
3.config数据库
当 MongoDB 使用分片设置时,config 数据库可用来保存分片的相关信息
1.建立索引
db.集合名.createIndex( {age: 1} )
2.MongoDB索引类型
db.person.createIndex( {age: 1, name: 1} )
MongoDB支持多种类型的索引,包括单字段索引、复合索引、多key索引、文本索引等,每种类型的索引有不同的使用场合。
2.1 多key索引 (Multikey Index)
当索引的字段为数组时,创建出的索引称为多key索引,多key索引会为数组的每个元素建立一条索引
{"name" : "jack", "age" : 19, habbit: ["football, runnning"]}
db.person.createIndex( {habbit: 1} ) // 自动创建多key索引
db.person.find( {habbit: "football"} )
2.2 其他类型索引
哈希索引(Hashed Index)是指按照某个字段的hash值来建立索引,目前主要用于MongoDB Sharded Cluster的Hash分片,hash索引只能满足字段完全匹配的查询,不能满足范围查询等。
地理位置索引(Geospatial Index)能很好的解决O2O的应用场景,比如『查找附近的美食』、『查找某个区域内的车站』等。
文本索引(Text Index)能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引
2.3 索引额外属性
MongoDB除了支持多种不同类型的索引,还能对索引定制一些特殊的属性。
唯一索引 (unique index):保证索引对应的字段不会出现相同的值,比如_id索引就是唯一索引
TTL索引:可以针对某个时间字段,指定文档的过期时间(经过指定时间后过期 或 在某个时间点过期)
部分索引 (partial index): 只针对符合某个特定条件的文档建立索引,3.2版本才支持该特性
稀疏索引(sparse index): 只针对存在索引字段的文档建立索引,可看做是部分索引的一种特殊情况
2.4 索引优化 db profiling
MongoDB支持对DB的请求进行profiling,目前支持3种级别的profiling。
0:不开启profiling
1:将处理时间超过某个阈值(默认100ms)的请求都记录到DB下的system.profile集合 (类似于mysql、redis的slowlog)
2:将所有的请求都记录到DB下的system.profile集合(生产环境慎用)
db.collection.explain()
explain有三种模式,分别是:①queryPlanner、②executionStats、③allPlansExecution
1.COLLSCAN:代表该查询进行了全表扫描;
2.IXSCAN:代表进行了索引扫描;
3.keysExamined:代表索引扫描条目;
4.docsExamined:代表文档扫描条目。
4.Springboot集成MongoDB
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
spring.data.mongodb.uri=mongodb://adminUser:adminPass@localhost:27017/authSource=admin&authMechanism=SCRAM-SHA-1
spring.data.mongodb.database=users
多个 IP 集群可以采用以下配置:
spring.data.mongodb.uri=mongodb://user:pwd@ip1:port1,ip2:port2/databases
mongodb:
address: localhost:27017
database: soms
username: admin
password: 123456
clientName: soms-task
connectionTimeoutMs: 10000
readTimeoutMs: 15000
poolMaxWaitTimeMs: 3000
connectionMaxIdleTimeMs: 60000
connectionMaxLifeTimeMs: 120000
heartbeatFrequencyMs: 20000
minHeartbeatFrequencyMs: 8000
heartbeatConnectionTimeoutMs: 10000
heartbeatReadTimeoutMs: 15000
connectionsPerHost: 100
minConnectionsPerHost: 5
threadsAllowedToBlockForConnectionMultiplier: 10
1.工具类
package com.wcf.mongo.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.ListIndexesIterable;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.Indexes;
import com.wcf.mongo.entity.MongoBaseInfo;
import org.bson.Document;
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 org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class SimpleMongoServiceImpl<T extends MongoBaseInfo> implements SimpleMongoService<T> {
@Autowired
private MongoTemplate mongoTemplate;
@Override
public void createCollection(String name) {
mongoTemplate.createCollection(name);
}
@Override
public String createIndex(String collectionName, String filedName) {
IndexOptions options = new IndexOptions();
options.unique(true);
return mongoTemplate.getCollection(collectionName).createIndex(Indexes.ascending(filedName), options);
}
@Override
public List<String> getAllIndexes(String collectionName) {
ListIndexesIterable<Document> list = mongoTemplate.getCollection(collectionName).listIndexes();
List<String> indexes = new ArrayList<>();
for (Document document : list) {
document.entrySet().forEach((key) -> {
if (key.getKey().equals("name")) {
indexes.add(key.getValue().toString());
}
});
}
return indexes;
}
@Override
public void insert(T info, String collectionName) {
mongoTemplate.insert(info, collectionName);
}
@Override
public void insertMulti(List<T> infos, String collectionName) {
mongoTemplate.insert(infos, collectionName);
}
@Override
public void updateById(String id, String collectionName, T info) {
Query query = new Query(Criteria.where("id").is(id));
Update update = new Update();
String str = JSON.toJSONString(info);
JSONObject jQuery = JSON.parseObject(str);
jQuery.forEach((key, value) -> {
if (!key.equals("id")) {
update.set(key, value);
}
});
mongoTemplate.updateMulti(query, update, info.getClass(), collectionName);
}
@Override
public void deleteById(String id, Class<T> clazz, String collectionName) {
Query query = new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query, clazz, collectionName);
}
@Override
public T selectById(String id, Class<T> clazz, String collectionName) {
return mongoTemplate.findById(id, clazz, collectionName);
}
@Override
public List<T> selectList(String collectName, Class<T> clazz) {
return selectList(collectName, clazz, null, null);
}
@Override
public List<T> selectList(String collectName, Class<T> clazz, Integer currentPage, Integer pageSize) {
Query query = new Query();
if (!ObjectUtils.isEmpty(currentPage) && ObjectUtils.isEmpty(pageSize)) {
query.limit(pageSize);
query.skip(pageSize * (currentPage - 1));
}
return mongoTemplate.find(query, clazz, collectName);
}
@Override
public List<T> selectByCondition(String collectName, Map<String, String> conditions, Class<T> clazz, Integer currentPage, Integer pageSize) {
if (ObjectUtils.isEmpty(conditions)) {
return selectList(collectName, clazz, currentPage, pageSize);
} else {
Query query = new Query();
query.limit(pageSize);
query.skip(currentPage);
conditions.forEach((key, value) -> query.addCriteria(Criteria.where(key).is(value)));
return mongoTemplate.find(query, clazz, collectName);
}
}
}
2.配置类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
@Data
@Validated
@Component
@ConfigurationProperties(prefix = "mongodb")
public class MongoClientOptionProperties {
private String database;
private String username;
private String password;
@NotNull
private List<String> address;
@NotNull
@Size(min = 1)
private String clientName;
@Min(value = 1)
private int connectionTimeoutMs;
@Min(value = 1)
private int readTimeoutMs;
@Min(value = 1)
private int poolMaxWaitTimeMs;
@Min(value = 1)
private int connectionMaxIdleTimeMs;
@Min(value = 1)
private int connectionMaxLifeTimeMs;
@Min(value = 2000)
private int heartbeatFrequencyMs;
@Min(value = 300)
private int minHeartbeatFrequencyMs;
@Min(value = 1)
private int threadsAllowedToBlockForConnectionMultiplier;
@Min(value = 200)
private int heartbeatConnectionTimeoutMs;
@Min(value = 200)
private int heartbeatReadTimeoutMs;
@Min(value = 1)
private int connectionsPerHost;
@Min(value = 1)
private int minConnectionsPerHost;
3.连接池配置
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.*;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class MongoConfig {
private final Logger log = LoggerFactory.getLogger(MongoConfig.class);
@Bean
@Autowired public MongoDbFactory mongoDbFactory(MongoClientOptionProperties properties) {
MongoClientOptions options = mongoClientOptions(properties);
List<ServerAddress> serverAddresses = new ArrayList<>();
for (String address : properties.getAddress()) {
String[] hostAndPort = address.split(":");
String host = hostAndPort[0];
int port = Integer.parseInt(hostAndPort[1]);
ServerAddress serverAddress = new ServerAddress(host, port);
serverAddresses.add(serverAddress);
}
String username = properties.getUsername();
String password = properties.getPassword();
String database = properties.getDatabase();
MongoClient mongoClient;
if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(
username,
database,
password.toCharArray());
mongoClient = new MongoClient(serverAddresses.get(0), mongoCredential, options);
} else {
mongoClient = new MongoClient(serverAddresses, options);
}
SimpleMongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, database);
log.info("mongodb注入成功");
return mongoDbFactory;
}
@Bean(name = "mongoTemplate")
@Autowired
public MongoTemplate getMongoTemplate(MongoDbFactory mongoDbFactory) {
return new MongoTemplate(mongoDbFactory);
}
public MongoClientOptions mongoClientOptions(MongoClientOptionProperties properties) {
return MongoClientOptions.builder()
.connectTimeout(properties.getConnectionTimeoutMs())
.socketTimeout(properties.getReadTimeoutMs()).applicationName(properties.getClientName())
.heartbeatConnectTimeout(properties.getHeartbeatConnectionTimeoutMs())
.heartbeatSocketTimeout(properties.getHeartbeatReadTimeoutMs())
.heartbeatFrequency(properties.getHeartbeatFrequencyMs())
.minHeartbeatFrequency(properties.getMinHeartbeatFrequencyMs())
.maxConnectionIdleTime(properties.getConnectionMaxIdleTimeMs())
.maxConnectionLifeTime(properties.getConnectionMaxLifeTimeMs())
.maxWaitTime(properties.getPoolMaxWaitTimeMs())
.connectionsPerHost(properties.getConnectionsPerHost())
.threadsAllowedToBlockForConnectionMultiplier(
properties.getThreadsAllowedToBlockForConnectionMultiplier())
.minConnectionsPerHost(properties.getMinConnectionsPerHost()).build();
}
@Bean
public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
try {
mappingConverter.setCustomConversions(beanFactory.getBean(MongoCustomConversions.class));
} catch (NoSuchBeanDefinitionException ignore) {
}
mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mappingConverter;
}
}
4.集成问题
1.mongodb 3.0认证问题
MongoDB 3.0新增了一种认证机制(authenticationMechanisms) SCRAM-SHA-1, 并把他设置为默认的方式. 而Spring Boot里默认使用旧的认证机制.
解决办法:
1) 把Mongodb的认证机制改了: mongodb支持如下几种:
SCRAM-SHA-1
MONGODB-CR
MONGODB-X509
GSSAPI (Kerberos)
PLAIN (LDAP SASL)
把Mongodb的认证方式改变一下自然能解决问题. 可以同时支持多个.
setParameter:
authenticationMechanisms: MONGODB-CR,SCRAM-SHA-1
enableLocalhostAuthBypass: false
logLevel: 4
2)改变Springboot认证方式
org.springframework.boot.autoconfigure.mongo.MongoProperties 的 createMongoClient方法
2.解决SpringBoot MongoDB插入文档默认生成_class字段问题
@Configuration
public class SpringMongoConfig{
@Bean
public MongoTemplate mongoTemplate() throws Exception {
MappingMongoConverter converter =
new MappingMongoConverter(mongoDbFactory(), new MongoMappingContext());
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory(), converter);
return mongoTemplate;
}
}
3.spring boot 集成mongodb 开启事务
@Configuration
public class TransactionConfig {
@Bean
MongoTransactionManager transactionManager(MongoDbFactory factory){
return new MongoTransactionManager(factory);
}
}