上几篇博客简单对MongoDB进行了简单介绍和如何安装,以及在dos下是如何操作MongoDB和在安装MongoDB中,出现了什么错误,是如何解决的。当然这些都还不够,我们还要用到实际当中去。我用MyEclipse+JDK1.7做了一个简单的demo,来展示下MongoDB怎么运用到实际中去。
MongoDB作为一个NoSql数据库的代表,存取多媒体数据,应该是强项吧?那么,在MongoDB中是如何对图片进行CRUD操作的。
上几篇博客中已经提到,MongoDB的文档结构是BSON格式,BSON格式本身支持保存二进制格式的数据,所以可以把文件的二进制格式的数据直接保存到MongoDB的文档结构中。但是一个BSON的最大长度不能超过4M,所以限制了单个文档中能存入的最大文件不能超过4M。为了解决这个问题,MongoDB提供了“GridFS”方式,“GridFS”方式对文件操作需要引入相关jar包——mongo-java-driver-2.9.3.jar。
不多说,看实例:
package com.zd.mongodb.common; import java.io.File; import java.io.IOException; import java.net.UnknownHostException; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.gridfs.GridFS; import com.mongodb.gridfs.GridFSDBFile; import com.mongodb.gridfs.GridFSInputFile; public class MongoDBCommon { // 连接mongodb public DB MongoDbConnection() { Mongo m = null; try { m = new Mongo("localhost", 27017); } catch (UnknownHostException e) { e.printStackTrace(); } DB db = m.getDB("test"); return db; } // 保存图片信息 public void saveFile(String connection, String id, String file) { DB db = MongoDbConnection(); //获取MongoDB的数据库 File imageFile = new File(file); GridFS gfsPhoto = new GridFS(db, connection); //connection为集合名词 GridFSInputFile gfsFile = null; try { gfsFile = gfsPhoto.createFile(imageFile); } catch (IOException e) { e.printStackTrace(); } gfsFile.setId(id); gfsFile.setContentType("image/jpeg"); gfsFile.save(); } // 读取文件 public void readFile(String connection, String fileName) { DB db = MongoDbConnection(); //获取连接 DBCollection collection = db.getCollection(connection); //connection为集合名称 String newFileName = fileName; GridFS gfsPhoto = new GridFS(db, connection); GridFSDBFile imageForOutput = gfsPhoto.findOne(newFileName); System.out.println(imageForOutput); <span style="font-family: Arial, Helvetica, sans-serif;">//返回数据以BSON格式体现</span> } //根据id查询相应文件 public void findByObjectId(String connection, String id) { DB db = MongoDbConnection(); DBCollection collection = db.getCollection(connection); DBObject dbObj = collection.findOne(id); System.out.println(dbObj); //返回数据以BSON格式体现 } // 删除文件 public void deleteFile(String connection,String id) { DB db = MongoDbConnection(); DBCollection collection = db.getCollection(connection); DBObject o=collection.findOne(id); collection.remove(o); } }
客户端:
package com.zd.mongodb.common; public class ZhudanTest { <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> public static void main(String[] args) throws Exception { <span style="white-space:pre"> </span> MongoDBCommon dbCommon=new MongoDBCommon(); <span style="white-space:pre"> </span> String newFileName="zhudan.jpg"; <span style="white-space:pre"> </span> String imageFile="D:/生活/照片/me/zhudan.jpg"; //<span style="white-space:pre"> </span> String connection="photo.files"; <span style="white-space:pre"> </span> String connection="photo"; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //根据id保存数据 <span style="white-space:pre"> </span> String id="1111"; <span style="white-space:pre"> </span> dbCommon.saveFile( connection, id, imageFile); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //根据名称获取数据 //<span style="white-space:pre"> </span> dbCommon.readFile(connection, newFileName); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //根据id删除数据 //<span style="white-space:pre"> </span> String id="1111"; //<span style="white-space:pre"> </span> dbCommon.deleteFile(connection,id); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> //根据id查询数据 //<span style="white-space:pre"> </span> String id="1111"; //<span style="white-space:pre"> </span> dbCommon.findByObjectId(connection, id); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span> } }
以图为证:
再分析下原理:
创建photo时,驱动首先会在当前数据库创建两个集合:一个是"photo.files"集合,另一个是"photo.chunks"集合,前者记录了文件名,文件创建时间,文件类型等基本信息;后者分块存储了文件的二进制数据(并支持加密这些二进制数据)。
一个trunk有一个默认的大小,当文件超过这个默认大小后,会把文件分割成多个chunk,再把这些chunk保存到photo.chunks中,最后再把文件信息存入到photo.files中。
在读取文件的时候,先根据查询条件,在photo.files中找到一个合适的记录,得到“_id”的值,再据这个值到photo.chunks中查找所有“files_id”为“_id”的chunk,并按“n”排序,最后依次读取chunk中“data”对象的内容,还原成原来的文件。
说到原理,我在测试的过程中,在保存图片的时候,我需要用的集合名称是photo,在读取和删除图片的时候,我需要用的完整集合名称是photo.files。如果此时我用集合名未photo时,查找不到相关数据。
总结:
MongoDB作为一个NoSql数据库的代表,其实它里面包含的东西还有很多,我所接触到的也只是冰山一角,为以后的MongoDB的学习做一个小小的准备。