1 MongoDB简介
MongoDB是一个基于分布式文件存储的数据库开源项目。由C++语言编写,旨在为WEB应用提供可护展的高性能数据存储解决方案。它的特点是可扩展,高性能,易使用,模式自由,存储数据非常方便等。
1.1 主要功能特性
a)面向文档存储:(类JSON数据模式简单而强大)。b)高效的传统存储方式:支持二进制数据及大型对象(如照片和视频)。c)复制及自动故障转移:Mongo数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。d)Auto-Sharding自动分片支持云级扩展性(处于早期alpha阶段):自动分片功能支持水平的数据库集群,可动态添加额外的机器。e)动态查询:它支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。f)全索引支持:包括文档内嵌对象及数组。Mongo的查询优化器会分析查询表达式,并生成一个高效的查询计划。g)支持RUBY,PYTHON,JAVA,C++,PHP等多种语言。
1.2 适用场景
a)适合实时的插入,更新与查询,并具备应用程序实时数据存储所需的复制及高度伸缩性。
b)适合作为信息基础设施的持久化缓存层。
c)适合由数十或数百台服务器组成的数据库。因为Mongo已经包含对MapReduce引擎的内置支持。
d)Mongo的BSON数据格式非常适合文档化格式的存储及查询。
1.3 不适用场景
a)高度事务性的系统。
b)传统的商业智能应用。
c)级为复杂的SQL查询。
1.4 其他使用场景参考
1.4.1你期望一个更高的写负载
默认情况下,对比事务安全,MongoDB更关注高的插入速度。如果你需要加载大量低价值的业务数据,那么MongoDB将很适合你的用例。但是必须避免在要求高事务安全的情景下使用MongoDB,比如一个1000万美元的交易。1.4.2不可靠环境保证高可用性
设置副本集(主-从服务器设置)不仅方便而且很快,此外,使用MongoDB还可以快速、安全及自动化的实现节点(或数据中心)故障转移。1.4.3未来会有一个很大的规模
数据库扩展是非常有挑战性的,当单表格大小达到5-10GB时,MySQL表格性能会毫无疑问的降低。如果你需要分片并且分割你的数据库,MongoDB将很容易实现这一点。1.4.4使用基于位置的数据查询
MongoDB支持二维空间索引,因此可以快速及精确的从指定位置获取数据。1.4.5非结构化数据的爆发增长
给RDBMS增加列在有些情况下可能锁定整个数据库,或者增加负载从而导致性能下降,这个问题通常发生在表格大于1GB(更是下文提到BillRun系统中的痛点——单表格动辄几GB)的情况下。鉴于MongoDB的弱数据结构模式,添加1个新字段不会对旧表格有任何影响,整个过程会非常快速;因此,在应用程序发生改变时,你不需要专门的1个DBA去修改数据库模式。2 与spring配置集成
2.1 包结构
2.2pom文件配置
<dependencies>
<dependency>
<groupId>com.qfang</groupId>
<artifactId>qfang-model</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.6.2.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.1.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
2.3 spring配置文件
<?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:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.qfang.mongo" />
<mongo:mongo host="192.168.235.135" port="27017" />
<!-- mongo的工厂,通过它来取得mongo实例,dbname为mongodb的数据库名,没有的话会自动创建 -->
<mongo:db-factory dbname="test" mongo-ref="mongo" />
<!-- mongodb的主要操作对象,所有对mongodb的增删改查的操作都是通过它完成 -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<!-- 映射转换器,扫描back-package目录下的文件,根据注释,把它们作为mongodb的一个collection的映射 -->
<mongo:mapping-converter base-package="com.qfang.mongo" />
<!-- mongodb bean的仓库目录,会自动扫描扩展了MongoRepository接口的接口进行注入 -->
<mongo:repositories base-package="com.qfang.mongo" />
<context:annotation-config />
</beans>
2.4集合映射类
package com.qfang.mongo.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* 集合映射
* @author yoara
*/
@Document(collection="first")
public class First {
@Id
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2.5 数据操作
package com.qfang.mongo;
public interface FirstDao {
long count();
}
package com.qfang.mongo.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import com.qfang.mongo.FirstDao;
import com.qfang.mongo.model.First;
@Repository("firstDao")
public class FirstDaoImpl implements FirstDao{
@Autowired
private MongoTemplate mongoTemplate;
public long count() {
Query q = new Query();
return mongoTemplate.count(q, First.class);
}
}
2.6 测试用例
package com.qfang.mongo;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext-mongo-test.xml"})
public class AbstractTest {
@Before
public void setUp(){
}
}
package com.qfang.mongo.impl;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.qfang.mongo.AbstractTest;
import com.qfang.mongo.FirstDao;
public class FirstDaoImplTest extends AbstractTest{
@Autowired
private FirstDao firstDao;
@Test
public void testCount() {
Assert.assertEquals(2l, firstDao.count());
}
}
实际上,集成spring后mongodb原本自由的格式,被强制统一到spring的通用使用方式上,template的使用类似于ORM框架,映射关系不想原生的bson格式灵活,建议还是直接用mongo-java-driver去做。
spring的底层实现也是mongo-java-driver,该包自带了连接池内有默认配置为100。
3 mongodb使用
上面的环境搭建好后,测试用例要跑起来还是需要数据。
mongodb的安装就不说了,本人装在192.168.235.135的ubuntu虚拟机上。外部连接需要放开/etc/mongod.conf 的bind_ip属性限制
3.1 mongodb常用命令
查询游标方法
名称 | 说明 |
cursor.count() | 返回游标中的文档的数量。 |
cursor.explain() | 报告的查询执行计划,包括索引使用的游标。 |
cursor.hint() | 若要使用查询的特定索引的部队 MongoDB。 |
cursor.limit() | 约束游标的结果集的大小。 |
cursor.next() | 返回游标中的下一个文档。 |
cursor.skip() | 返回一个游标,开始传递或跳过的一些文件后才返回结果。 |
cursor.sort() | 返回结果排序根据排序的规范。 |
cursor.toArray() | 返回一个数组,包含由光标返回的所有文档。 |
名称 | 说明 |
db.collection.insert() | 在集合中创建一个新文档。 |
db.collection.save() | 提供insert()和update ()插入新文件的包装。 |
db.collection.update() | 修改集合中的文档。 |
db.collection.find() | 集合上执行查询,并返回一个游标对象。 |
db.collection.findOne() | 执行查询,并返回一个单独的文档。 |
db.collection.remove() | 从集合中删除的文件。 |
db.collection.count() | 换行计数集合或匹配查询中返回的文档数的计数。 |
db.collection.distinct() | 返回一个数组没有指定的字段不重复值的文件。 |
从配置文件中可以看出,我建了test库,并新建了first集合。具体的数据操作就留给大家了。