mongdb

MongoDB
http://lib.csdn.net/base/mongodb
http://blog.csdn.net/Flyfish111222/article/details/51891130
Introduction
MongoDB 是一个是一个基于分布式文件存储的数据库,介于关系数据库和非关系数据库之间,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,
是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系
数据库单表查询的绝大部分功能,而且还支持对数据建立索引

安装MongoDB
    sudo apt-get install mongodb
    mongo -version

启动、关闭数据库(默认设置MongoDB是随Ubuntu启动自动启动的。)
    service mongodb start
    service mongodb stop

查看是否启动成功:
    pgrep mongo -l   #注意:-l是英文字母l,不是阿拉伯数字1  

卸载MongoDB
    sudo apt-get --purge remove mongodb mongodb-clients mongodb-server

使用MongoDB
    输入mongo进入shell命令模式,默认连接的数据库是test数据库,在此之前一定要确保你已经启动了MongoDB
        mongo
        显示shell脚本表示成功,连接test

    常用操作命令:
        show dbs:显示数据库列表 
        show collections:显示当前数据库中的集合(类似关系数据库中的表table) 
        show users:显示所有用户 
        use DBName:切换当前数据库至DBName
        db.help() :显示数据库操作命令 
        db.CollectionName.help() : 显示集合操作命令,CollectionName是集合名 

    创建库和集合
        MongoDB没有创建数据库的命令,如果你想创建一个“School”的数据库,先运行use School命令,之后做一些操作(如:创建聚集集合db.createCollection('teacher')),
        这样就可以创建一个名叫“School”的数据库,并且创建一个集合teacher. 

        集合也可以不创建,直接添加数据,会自动创建数据,  不需要预先定义 collection 

        切换数据库
            use School #切换到School数据库。MongoDB 无需预创建School数据库,在使用时会自动创建
        创建Collection
            db.createCollection('teacher') #创建一个聚集集合。MongoDB 其实在插入数据的时候,也会自动创建对应的集合,无需预定义集合

    插入数据
        插入数据有两种方式:insert和save。
        这两种方式,其插入的数据中_id字段均可不写,会自动生成一个唯一的_id来标识本条数据
        insert和save不同之处在于:
            在手动插入_id字段时,如果_id已经存在,insert不做操作,save做更新操作;如果不加_id字段,两者作用相同都是插入数据
            db.student.insert({_id:1, sname: 'zhangsan', sage: 20}) #_id可选
            db.student.save({_id:1, sname: 'zhangsan', sage: 22}) #_id可选

        数据操作
            db.student.insert({_id:1, sname: 'zhangsan', sage: 20}) 
            db.student.find();
                { "_id : 1, "sname" : "zhangsan", "sage" : 20 } 插入成功

            db.student.save({_id:1, sname: 'zhangsan', sage: 22}) 
            db.student.find();
                { "_id : 1, "sname" : "zhangsan", "sage" : 22 } id 相同, save更新数据成功

            db.student.insert({_id:1, sname: 'zhangsan', sage: 25}) 
            db.student.find();
                { "_id : 1, "sname" : "zhangsan", "sage" : 22 } id 相同, insert更新数据失败,不做更改

    查找数据
        db.youCollection.find(criteria, filterDisplay)
            criteria :查询条件,可选 
            filterDisplay:筛选显示部分数据,如显示指定列数据,可选(当选择时,第一个参数不可省略,若查询条件为空,可用{}做占位符,如下面第三句

        etc:
            db.student.find()  #查询所有记录。相当于:select * from student
            db.student.find({sname: 'lisi'})  #查询sname='lisi'的记录。相当于: select * from student where sname='lisi'
            db.student.find({},{sname:1, sage:1}) #查询指定列sname、sage数据。相当于:select sname,sage from student。sname:1
                表示返回sname列,默认_id字段也是返回的,可以添加_id:0(意为不返回_id)写成{sname: 1, sage: 1,_id:0},就不会返回默认的_id字段了
            db.student.find({sname: 'zhangsan', sage: 22}) #and 与条件查询。相当于:select * from student where sname = 'zhangsan' and sage = 22
            db.student.find({$or: [{sage: 22}, {sage: 25}]}) #or 条件查询。相当于:select * from student where sage = 22 or sage = 25

    修改数据 
        db.youCollection.update(criteria, objNew, upsert, multi ), criteria和objNew是必选参数,upsert和multi可选参数 
            criteria: update的查询条件,类似sql update查询内where后面的 
            objNew : update的对象和一些更新的操作符(如$set)等,也可以理解为sql update查询内set后面的。
            upsert : 如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。 
            multi: mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。默认false,只修改匹配到的第一条数据。

        db.student.update({sname: 'lisi'}, {$set: {sage: 30}}, false, true) #相当于:update student set sage =30 where sname = 'lisi';

    删除数据
        db.student.remove({sname: 'chenliu'}) #相当于:delete from student where sname='chenliu'

    退出shell命令模式 
        输入exit或者Ctrl+C退出shell命令模式

注意:MongoDB相较安全性更偏向易用性,默认是没有开启用户权限的,如果想开启用户权限,可以参考http://blog.csdn.net/Flyfish111222/article/details/51886840

Java API编程实例

    添加jar包
        mongo-java-driver-3.2.2.jar

    <!--

        import java.util.ArrayList;
        import java.util.List;

        import org.bson.Document;
        import com.mongodb.MongoClient;
        import com.mongodb.client.MongoCollection;
        import com.mongodb.client.MongoCursor;
        import com.mongodb.client.MongoDatabase;
        import com.mongodb.client.model.Filters;

        public class TestMongoDB {

            /**
             * @param args
             */
            public static void main(String[] args) {
            insert();//插入数据。执行插入时,可将其他三句函数调用语句注释掉,下同
        //      find(); //查找数据
        //      update();//更新数据
        //      delete();//删除数据
            }
            /**
             * 返回指定数据库中的指定集合
             * @param dbname 数据库名
             * @param collectionname 集合名
             * @return
             */
            //MongoDB无需预定义数据库和集合,在使用的时候会自动创建
            public static MongoCollection<Document> getCollection(String dbname,String collectionname){
            //实例化一个mongo客户端,服务器地址:localhost(本地),端口号:27017
            MongoClient  mongoClient=new MongoClient("localhost",27017);
            //实例化一个mongo数据库
            MongoDatabase mongoDatabase = mongoClient.getDatabase(dbname);
            //获取数据库中某个集合
            MongoCollection<Document> collection = mongoDatabase.getCollection(collectionname);
            return collection;
            }
            /**
             * 插入数据
             */
            public static void insert(){
            try{
                //连接MongoDB,指定连接数据库名,指定连接表名。
                MongoCollection<Document> collection= getCollection("test","student");
                //实例化一个文档,文档内容为{sname:'Mary',sage:25},如果还有其他字段,可以继续追加append
                Document doc1=new Document("sname","Mary").append("sage", 25);
                //实例化一个文档,文档内容为{sname:'Bob',sage:20}
                Document doc2=new Document("sname","Bob").append("sage", 20);
                List<Document> documents = new ArrayList<Document>(); 
                //将doc1、doc2加入到documents列表中
                documents.add(doc1); 
                documents.add(doc2); 
                //将documents插入集合
                collection.insertMany(documents);  
                System.out.println("插入成功"); 
            }catch(Exception e){
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );
            }
            }
            /**
             * 查询数据
             */
            public static void find(){
            try{
                MongoCollection<Document> collection = getCollection("test","student");
                //通过游标遍历检索出的文档集合 
            //MongoCursor<Document>  cursor= collection.find(new Document("sname","Mary")). projection(new Document("sname",1).append("sage",1).append("_id", 0)).iterator();   
            //find查询条件:sname='Mary'。projection筛选:显示sname和sage,不显示_id(_id默认会显示)
                //查询所有数据
                MongoCursor<Document>  cursor= collection.find().iterator();
                while(cursor.hasNext()){
                System.out.println(cursor.next().toJson());
                }
            }catch(Exception e){
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );
            }
            }
            /**
             * 更新数据
             */
            public static void update(){
            try{
                MongoCollection<Document> collection = getCollection("test","student");
                 //更新文档   将文档中sname='Mary'的文档修改为sage=22   
                 collection.updateMany(Filters.eq("sname", "Mary"), new Document("$set",new Document("sage",22)));  
                 System.out.println("更新成功!");
            }catch(Exception e){
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );
            }
            }
            /**
             * 删除数据
             */
            public static void delete(){
            try{
                MongoCollection<Document> collection = getCollection("test","student");
                //删除符合条件的第一个文档  
                collection.deleteOne(Filters.eq("sname", "Bob"));  
                //删除所有符合条件的文档  
                //collection.deleteMany (Filters.eq("sname", "Bob"));
                System.out.println("删除成功!");
            }catch(Exception e){
                System.err.println( e.getClass().getName() + ": " + e.getMessage() );
            }
            }
        }       

    -->

MongoDB 用户权限
    Introduction
        MongoDB默认是没有开启用户权限的,如果直接在公网服务器上如此搭建mongodb,那么所有人都可以直接访问并修改数据库数据了。 
        其实MongoDB本身有非常详细的安全配置准则,显然开发者也是想到了,然而他是将安全的任务推给用户去解决,这本身的策略就是偏向易用性的,对于安全性,则得靠边站了。
        MongoDB有两种用户,一种是admin用户(这里以root为例),能查看所有数据库;另一种数据库用户(这里以dbuser为例)

    首先输入mongo进入MongoDB shell命令模式:
        mongo

    在admin表中添加root用户,在test表中添加dbuser用户
        use admin
        db.addUser('root','123') #用户名:root,密码:123   
        use test
        db.addUser('dbuser','123') #用户名:dbuser,密码:123

        MongoDB所有的用户信息都是存储在admin数据库中system.users表中,截图如下: 
            db.system.users.find()

    修改/etc/mongodb.conf,设置auth=true
        sudo vim /etc/mongodb.conf  //取消注释

    重启MongoDB
        service mongodb stop  #停止MongoDB服务(因为MongoDB是随开机是自启动的)
        service mongodb start #开启MongoDB服务

    测试用户权限是否正常开启 
        试图查看test数据库的所有集合,发现查看失败;验证test数据库用户dbuser;再次查看test所有集合,发现查看成功. 
            show collections failed
            db.auth('dbuser','123')  1,表示成功
            show collections success

        试图查看School数据库的所有集合,发现查看失败,因为dbuser是test数据库的用户,无法验证School数据库;
        切换到admin数据库,验证root用户名;再切换回School数据库,查看其所有集合,发现查看成功
            use school
            show collections failed

            use admin
            db.auth('root', '123') 1,用户验证成功

            use School
            show collections  success

        注:
            这里需要指出的是,验证用户不是切换用户,只要验证过用户,就拥有了对该数据库的操作权限,如我先验证了root用户,再验证dbuser用户(test数据库的用户),
            依然可以操作School数据库,因为验证过root用户,仅对当次shell模式有效,退出shell之后再进入shell需要重新验证。


MongoDB的安装包安装和使用
    获取安装包

    将安装包解压到/usr/local,并将解压的文件夹重命名为mongodb
        sudo tar -zxf ~/Downloads/mongodb-linux-x86_64-ubuntu1604-3.2.7.tgz -C /usr/local
        cd /usr/local
        sudo mv mongodb-linux-x86_64-ubuntu1604-3.2.7 mongodb

    创建文件夹/data/db/journal,创建文件mongodb.log, 拟将/data/db作为数据保存目录,/data/db/journal/mongodb.log作为日志文件
        sudo mkdir -p /data/db/journal
        cd /data/db/journal
        touch mongodb.log

    创建并配置文件/etc/mongodb.conf
        sudo vim /etc/mongodb.conf   #没有/etc/mongodb.conf文件时用本条命令会自动创建/etc/mongodb.conf
        <!--
            #日志文件位置
            logpath=/data/db/journal/mongodb.log

            # 以追加方式写入日志
            logappend=true

            # 是否以守护进程方式运行
            fork = true

            # 默认27017
            #port = 27017

            # 数据库文件位置
            dbpath=/data/db

            # 启用定期记录CPU利用率和 I/O 等待
            #cpu = true

            # 是否以安全认证方式运行,默认是不认证的非安全方式
            #noauth = true
            #auth = true

            # 详细记录输出
            #verbose = true

            # Inspect all client data for validity on receipt (useful for
            # developing drivers)用于开发驱动程序时验证客户端请求
            #objcheck = true

            # Enable db quota management
            # 启用数据库配额管理
            #quota = true
            # 设置oplog记录等级
            # Set oplogging level where n is
            #   0=off (default)
            #   1=W
            #   2=R
            #   3=both
            #   7=W+some reads
            #diaglog=0

            # Diagnostic/debugging option 动态调试项
            #nocursors = true

            # Ignore query hints 忽略查询提示
            #nohints = true
            # 禁用http界面,默认为localhost:28017
            #nohttpinterface = true

            # 关闭服务器端脚本,这将极大的限制功能
            # Turns off server-side scripting.  This will result in greatly limited
            # functionality
            #noscripting = true
            # 关闭扫描表,任何查询将会是扫描失败
            # Turns off table scans.  Any query that would do a table scan fails.
            #notablescan = true
            # 关闭数据文件预分配
            # Disable data file preallocation.
            #noprealloc = true
            # 为新数据库指定.ns文件的大小,单位:MB
            # Specify .ns file size for new databases.
            # nssize =

            # Replication Options 复制选项
            # in replicated mongo databases, specify the replica set name here
            #replSet=setname
            # maximum size in megabytes for replication operation log
            #oplogSize=1024
            # path to a key file storing authentication info for connections
            # between replica set members
            #指定存储身份验证信息的密钥文件的路径
            #keyFile=/path/to/keyfile           
        -->

    脚本方式启动mongoDb服务
        cd /usr/local/mongodb
        ./bin/mongod -f /etc/mongodb.conf  forked process: 3709 success

    pgrep mongo -l可以查看是否启动成功
        3709 mongod

    进入mongoDb shell 模式
        cd /usr/local/mongodb
        ./bin/mongo

    关闭mongodb服务
        use admin
        db.shutdownServer()
        pgrep mongo -l 无, 表示成功退出mongoDb服务.

    卸载mongodb
        sudo apt-get --purge remove mongodb

代码片
    代码段1 curd 操作
        private static final int PORT = 27017;
 
        public static MongoClient getInstance() {
                return new MongoClient(IP, PORT);
            }
         
            public static void main(String args[]) {
                try {
                    // 连接到 mongodb 服务
                    MongoClient mongoClient = MongoUtils.getInstance();
                    // 连接到数据库
                    MongoDatabase db = mongoClient.getDatabase("test");
                    System.out.println("Connect to database successfully");
                     
                    MongoCollection dbc=db.getCollection("Order");
                     
                    Document doc=new Document();
                    //insert key
                    doc.put("name", "hello");
                    doc.put("age", "24");
                    doc.put("time", "2015-01-30");
                    dbc.insertOne(doc);
                    //del key
        //          dbc.deleteOne(doc);
                    System.out.println("总记录数>>"+dbc.count());
                } catch (Exception e) {
                    System.err.println(e.getClass().getName() + ": " + e.getMessage());
                }
            }

    代码段2 上传文件
        Mongo mongo = new Mongo();
        DB db = mongo.getDB("mongoDBFile");   //创建数据库连接
        GridFS myFS = new GridFS(db,"user1"); //创建GridFS   对mongoDBFile数据库中的user1进行操作,这样文件的读取和删除都是user1中的文件

        //保存文件
        GridFSFile file = myFS.createFile(new File("D:/image1.jpg"));
        file.save();

        //输出文件
        /*GridFSDBFile file =myFS.findOne("image1.jpg");
        file.writeTo(new File("D:/image1.jpg"));*/

         //删除文件
        /*GridFSDBFile file =myFS.findOne("image1.jpg");
        myFS.remove((ObjectId) file2.getId());*/

    代码段3 分页优化
            * 小于指定日期的所有根据UUID分组的访问记录
             * @param 指定日期
             * @return 所有访问记录的MAP
             */
            public static Multimap<String, Map<String, String>> getOldVisitors(String date){

            //每次查询的记录数
            int pagesize = 100000;

            //mongodb中的"_id"
            String objectId = "";

            //方法的返回值类型,此处用的google guava
            Multimap<String, Map<String, String>> mapless = null;

            //查询的条件
            BasicDBObject queryless = new BasicDBObject(),fields = new BasicDBObject(),field = new BasicDBObject();

            //初始化返回的mongodb集合操作对象,大家可以写个数据连接池
            dbCol = init();

            //查询指定字段,字段越少,查询越快,当然都是一些不必要字段
            field.put("uuid",1);

            fields.put("uuid", 1);

            fields.put("initTime", 1);

            //小于指定日期的条件
            String conditionless = TimeCond.getTimeCondless(date);

            queryless.put("$where", conditionless);

            DBCursor cursorless = dbCol.find(queryless,field);

            //MongoDB在小于指定日期条件下,集合总大小
            int countless = cursorless.count();

            //查询遍历的次数 circleCountless+1
            int circleCountless = countless/pagesize;

            //取模,这是最后一次循环遍历的次数
            int modless = countless%pagesize;

            //开始遍历查询
            for (int i = 1; i <=circleCountless+1; i++) {

                //文档对象
                DBObject obj = null;

                //将游标中返回的结果记录到list集合中,为什么放到list集合中?这是为后面guava 分组做准备
                List<Map<String, String>> listOfMaps = new ArrayList();

                //如果条件不为空,则加上此条件,构成多条件查询,这一步是分页的关键
                if (!"".equals(objectId)) {

                  //我们通过文档对象obj.get("_id")返回的是不带ObjectId(),所以要求此步骤
                           ObjectId id = new ObjectId(objectId);

                   queryless.append("_id", new BasicDBObject("$gt",id));

                }

                if (i<circleCountless+1) {

                cursorless = dbCol.find(queryless,fields).sort(new BasicDBObject("_id", 1)).limit(pagesize);

                }else if(i==circleCountless+1){//最后一次循环

                cursorless = dbCol.find(queryless,fields).limit(modless);
                }

                    //将游标中返回的结果记录到list集合中,为什么放到list集合中?这是为后面guava 分组做准备
                while (cursorless.hasNext()) {

                    obj = cursorless.next();

                    listOfMaps.add((Map<String, String>) obj);

                }
                //获取一次分页中最后一条记录的"_id",然后作为条件传入到下一个循环中
                if (null!=obj) {

                     objectId = obj.get("_id").toString();

                    }
                //第一次分组,根据uuid分组,分组除今天之外的历史数据
            mapless = Multimaps.index(
                      listOfMaps,new Function<Map<String, String>, String>() {
                      public String apply(final Map<String, String> from) {

                          return from.get("uuid"); 
                      }
                 });

            }  

            return mapless;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值