MongoDB介绍
- 什么是MongoDB
MongoDB是一个跨平台、面向文档的数据库,是当前NoSQL数据库产品中最热门的一种。介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的产品。它支持的数据结构非常松散,是类似JSON的BSON格式,可以存储比较复杂的数据类型。 - MongoDB特点
MongoDB最大的特点是它支持的查询语言非常强大,语法类似面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它是一个面向集合的,模式自由的文档型数据库。
- 面向集合存储,易于存储对象类型的数据
- 模式自由
- 支持动态查询
- 支持完全索引,包含内部对象
- 支持复制和故障恢复
- 使用高效的二进制数据存储,包括大型对象(如视频等)
- 自动处理碎片,以支持云计算层次的扩展性
- 支持多种语言的驱动程序
- 文件存储格式为BSON
- MongoDB体系结构
MongoDB的逻辑结构是一种层次结构:由文档(document)、集合(collection)、数据库(database)组成。逻辑结构是面向用户的,用户使用MongoDB开发应用程序使用的就是逻辑结构。
- 文档document,相当于关系数据库中的一行记录
- 多个文档组成一个集合collection,相当于关系数据库的表
- 多个集合collection,逻辑上组织在一起,就是数据库database
- 一个mongodb实例支持多个数据库database
Windows安装及启动
- 安装
官网下载安装即可。https://www.mongodb.com/
默认安装在C:\Program Files\MongoDB 目录下。需要启动的服务程序为C:\Program Files\MongoDB\Server\3.2\bin目录下的mongo.exe,可以添加到环境变量path中。 - 启动服务
Win+R ——》cmd 进入命令行:
创建一个用户存放数据的目录:md data\db
启动服务:mongod --dbpath=D:\MongoDB\data\db
–dbpath:指定数据存储的目录
–port:指定端口启动,默认端口27017
eg:mongod --port 12345 --dbpath=D:\MongoDB\data\db - 登录客户端
重新打开一个命令窗口,输入:mongo [ip:端口号]
退出命令:exit
基本增删改查操作
- 选择或创建数据库
查看全部数据库:show dbs;
查看当前所在数据库:db;或者db.getName();
选择数据库(不存在会自动创建):use test1;
显示数据库操作命令:db.help(); - 删除当前使用数据库:db.dropDatabase();
- 删除collection:db.student3.drop();
- 删除collection中所有记录:db.student3.remove();
- 插入文档
定义一个文档变量:变量名称={};
eg:s={name:‘悟空’,sex:‘男’,age:30,address:‘花果山水帘洞’}
将变量存入mongo:db.集合名称.save(变量);
eg:db.student.save(s);
# 集合不存在,会自动创建
不定义变量,直接向集合插入数据:
eg:db.student.save({name:‘八戒’,sex:‘男’,age:35,address:‘高老庄’});
测试数据:
db.student.save({name:“沙和尚”,sex:“男”,age:25,address:“流沙河路”});
db.student.save({name:“唐僧”,sex:“男”,age:35,address:“东土大唐”});
db.student.save({name:“白骨精”,sex:“女”,age:18,address:“白骨洞”});
db.student.save({name:“白龙马”,sex:“男”,age:20,address:“西海”});
db.student.save({name:“哪吒”,sex:“男”,age:15,address:“莲花湾”}); - 查询集合
显示当前数据库中的集合:show collections;
显示集合操作命令:db.集合名.help();
查询集合数据:db.集合名称.find()
![query-all](https://img-blog.csdnimg.cn/20181209093953241.)
字段_id,相当于关系型数据库中表的主键,插入文档时若没有指定,MongoDB会自动创建,类型为ObjectID。
插入文档时也可以指定_id,类型只要MongoDB支持即可。
eg:db.student.save({_id:1,name:“红孩儿”,sex:“男”,age:17,address:“火云洞”});
![条件查询](https://img-blog.csdnimg.cn/20181209094442250.)
为了避免游标可能带来的开销,MongoDB提供了findOne()方法,用来返回结果集的第一条记录。eg:db.student.findOne({sex:‘男’});
返回查询结果的前几条记录:db.student.find({sex:‘男’}).limit(3); - 修改文档
db.student.update({name:‘悟空’},{age:31});
![查询](https://img-blog.csdnimg.cn/20181209095501207.)
、# 查询发现悟空的文档只剩下_id和age两个字段了。。。
保留其他字段更新:db.student.update({name:‘八戒’},{$set:{age:28}}); - 删除文档
格式:db.集合名称.remove(条件);
# remove({}),慎用,会删除集合所有文档
eg:db.student.remove({name:‘哪吒’});
高级查询
- 模糊查询
MongoDB的模糊查询是通过正则表达式的方式实现的。
eg1:查询student集合中address字段中含有“洞”的所有文档
db.student.find({address:/洞/});
eg2:查询name字段中以“白”开头的
db.student.find({name:/^白/}); - Null值处理
db.student.update({name:‘唐僧’},{$set:{address:null}});
db.student.find({“address”:null});
![空值查询](https://img-blog.csdnimg.cn/20181209102220399.)
该方式查询会查询出该字段为null以及不存在该字段的文档记录。 - 大于小于
格式:db.collection.find({“field”: {$gt: value}});
- 大于:$gt
- 小于:$lt
- 大于等于:$gte
- 小于等于:$lte
eg:db.student.find({age: {$gte: 20}});
- 不等于:$ne
eg:db.student.find({sex: {$ne: “男”}}); - 判断字段是否存在:$exists
eg1:db.student.find({address: {$exists: true}});
eg1:db.student.find({address: {$exists: false}}); - 包含与不包含:$in
eg1:db.student.find({age: {$in: [20,25,30]}});
eg2:db.student.find({age: {$nin: [20,25,30]}}); - 统计记录条数:count()
eg1:db.student.count();
eg1:db.student.count({age: {$lte: 20}}); - 条件连接—并且:$and
格式:$and: [{}, {}]
eg:db.student.find({$and: [{age: {$gte: 20}}, {age: {$lt: 30}}]}); - 条件连接—或者:$or
格式:$or: [{}, {}]
eg:db.student.find({$or: [{sex: “女”}, {age: {$lt: 20}}]});
Java连接MongoDB
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.4.1</version>
</dependency>
- 查询文档
- MongoDB的数字类型默认使用64位浮点型数值,{x: 3.14}或{x: 3}。对于整型值,可以使用Numberint(4字节符号整数),{x: NumberInt(3)}或NumberLong(8字节符号整数){x: NumberLong(3)}
- MongoDB使用BasicDBObject类型封装查询条件
- 模糊查询
- 完全匹配:Pattern pattern = Pattern.compile("^name$");
- 右匹配:Pattern pattern = Pattern.compile("^.*name$");
- 左匹配:Pattern pattern = Pattern.compile("^name.*$");
- 模糊匹配:Pattern pattern = Pattern.compile("^.*name.*$");
// 遍历student集合所有数据:
MongoClient client = new MongoClient("127.0.0.1",27017);
MongoDatabase database = client.getDatabase("test1");
MongoCollection<Document> collection = database.getCollection("student");
FindIterable<Document> list = collection.find();
for (Document document : list) {
System.out.println("name="+document.getString("name"));
System.out.println("sex="+document.getString("sex"));
System.out.println("age="+document.getDouble("age"));
System.out.println("address="+document.getString("address"));
System.out.println("-----------------------");
}
// 匹配查询
BasicDBObject bson = new BasicDBObject("name", "八戒");
FindIterable<Document> list = collection.find(bson);
// 模糊查询
Pattern pattern = Pattern.compile("^白.*$");
BasicDBObject bson = new BasicDBObject("name", pattern);
FindIterable<Document> list = collection.find(bson);
//大于小于
BasicDBObject bson = new BasicDBObject("age", new BasicDBObject("$lt", 20));
// 条件连接—并且
BasicDBObject bson1 = new BasicDBObject("age", new BasicDBObject("$gte", 20));
BasicDBObject bson2 = new BasicDBObject("age", new BasicDBObject("$lt", 30));
BasicDBObject bson = new BasicDBObject("$and",Arrays.asList(bson1,bson2));
//条件连接—或者
BasicDBObject bson1 = new BasicDBObject("age", new BasicDBObject("$gte", 20));
BasicDBObject bson2 = new BasicDBObject("sex", "女");
BasicDBObject bson = new BasicDBObject("$or",Arrays.asList(bson1,bson2));
Map<String, Object> map = new HashMap();
map.put("name", "铁扇公主");
map.put("sex", "女");
map.put("age", 35.0);
map.put("address", "芭蕉洞");
Document doc = new Document(map);
collection.insertOne(doc);// 插入一条记录
// collection.insertMany(documents);//一次性插入多条文档
BasicDBObject bson=new BasicDBObject("name", "铁扇公主");
collection.deleteOne(bson);//删除记录(符合条件的第一条记录)
//collection.deleteMany(bson);//删除符合条件的全部记录
//修改的条件
BasicDBObject bson= new BasicDBObject("name", "红孩儿");
//修改后的值
BasicDBObject bson2 = new BasicDBObject("$set",new BasicDBObject("address", "南海"));
//参数1:修改条件 参数2:修改后的值,updateOne修改符合条件的第一条记录
collection.updateOne(bson, bson2);
//collection.updateMany(filter, update);//修改符合条件的所有记录
MongoDB连接池
- MongoClient被设计为线程安全的类,在使用时不需要考虑并发情况。可以把MongoClient做成一个静态变量,为所有线程公用,不必每次都销毁。这样可以极大提高执行效率。实际上,这是MongoDB提供的内置的连接池来实现的。
public class MongoManager {
private static MongoClient mongoClient = null;
//初始化mongoClient
private static void init() {
Builder builder = new MongoClientOptions.Builder();
builder.connectTimeout(5000);//设置连接超时时间
builder.socketTimeout(5000);//读取数据的超时时间
builder.connectionsPerHost(30);//每个地址最大请求数
builder.writeConcern(WriteConcern.NORMAL);//写入策略,仅抛出网络异常
MongoClientOptions options = builder.build();
mongoClient = new MongoClient(new ServerAddress("127.0.0.1", 27017),options);
}
public static MongoDatabase getDataBase() {
if(mongoClient == null) {
init();
}
return mongoClient.getDatabase("test1");
}
}
- 写入策略
WriteConcern.NONE:没有异常抛出
WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常
WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。
WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。
WriteConcern.FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。
WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。
WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。
Python连接MongoDB
# -*- coding: utf-8 -*-
# @Time :2018/12/9 22:11
# @File :testMongo.py
from pymongo import MongoClient
client = MongoClient("127.0.0.1", 27017)
collection = client["test1"]["student"]
def insertData():
ret = collection.insert([{"name": "test01", "age": 33}, {"name": "test02", "age": 35}])
print ret
def insertOne():
ret = collection.insert_one({"name": "test03", "age": 36})
print ret
def insertMany():
dict_list = [{"name": "test04", "age": 23}, {"name": "test05", "age": 25}]
collection.insert_many(dict_list)
def findOne():
ret = collection.find_one({"name": "八戒"})
print ret
def findAll():
ret = collection.find({})
for i in ret:
print "ret",i
for i in ret: # 结果是一个Cursor游标对象,此时没有结果
print "ret2",i
if __name__ == '__main__':
# findOne()
findAll()
# 增删改查类似