谷谷南

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

是在做知识分享时写的内容,分享给大家,也做个记录。

一、MongoDB介绍

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似 json 的 bson 格式,可以存储比较复杂的数据类型。

bson简称Binary JSON,BSON数据格式就是Json数据格式的二进制化,对于开发者而言,在使用及表现形式上两者是一致的。

MongoDB数据结构是由数据库(database)、集合(collection)、文档(document)三部分组成的。

Databases(数据库)

Databases(数据库)

Collection(集合)

Tables(数据表)

Document(文档)

Row(行)

其中,对于开发人员主要面对的是collection和document。其中数据文档(document)是数据载体,其数据格式定义如:{文档名:文档内容, 文档名:文档内容, 文档名:文档内容,….}

网上摘录了一些MongoDB的特点,如下:

  •  模式自由。支持动态查询、完全索引,可以方便地对文档中内嵌的对象及数组进行检索。
  •  面向文档存储。开发人员可以将现有的序列文档直接导入到MogonDB数据集中。
  •  高效的存储机制。MogonDB对数据并没有特殊的限制,任何数据(包括大型的图片、视频等)保存到MogonDB数据库中,最终都将被转换为二进制数据,从而在一定程度上保证读写的搞笑,以及确保数据完整、安全等。
  • 支持复制和故障恢复。提供了主-从、主-主模式的数据复制及服务器之间的数据复制。
  • 自动分片并支持云级别的伸缩性。支持水平的数据库集群,可以动态添加额外的服务器。
  • 支持Python、PHP、Ruby、Java、C、C#、JavaScript、Perl及C++语言的驱动程序。
  • 完全支持分布式架构。
  • Sphinx1.x开始支持MongoDB驱动。

 

下来看一下Mongodump导出的数据

 

这是从某库导出的数据,有两种文件,bson和metadata.json,bson是数据文件,metadata.json是元数据文件,用来存储表的定义和解释数据,用于数据库本身或用户进行分析,能大概了解数据库系统中的数据对象。

二、MongoDB安装

接下来看一下安装,有windows和linux版本,主要介绍linux的安装和使用,其实在linux下安装也很简单,网上有大量的资料,按照网上介绍的步骤安装就行,可以安装离线文件,也可在线安装。

 

1、 解压离线文件

tar zxf mongodb-linux-i686-1.8.2.tgz

2、 创建一个用来存储mongo的文件

mkdir /usr/local/mongodb

3、 将解压的文件移动到建好的文件夹中

mv mongodb-linux-i686-1.8.2 /usr/local/mongodb

4、 创建数据库文件和日志文件

cd /usr/local/mongodb

mkdir /usr/local/mongodb/data

mkdir /usr/local/mongodb/logs

 

上面这些做完后就可以启动了,设置一个开机自启动的设置

5、 开机自启动,将mongodb启动项目追加到系统文件(rc.local)中,保证mongodb在服务器开机时启动 

echo "/usr/local/server/mongodb/bin/mongod --dbpath=/usr/local/server/mongodb/data –logpath=/usr/local/server/mongodb/logs –logappend  --auth –port=27017" >> /etc/rc.local

6、 启动

./mongod --dbpath=/usr/local/mongodb/data --logpath=/usr/local/mongodb/logs --logappend  --port=27017 –fork

 

加入了fork选项,表示将mongod服务进程推送到后台运行,在看一下启动的其他参数

--dbpath:指定数据库目录,--logpath:指定日志存放目录,--port:指定通信端口,如果这个参数不加,默认是27017,加了就可以指定其他端口,如--port=27018

三、MongoDB使用

然后就可以通过GUI管理工具(mongovue、RockMongo、MongoHub)或命令行进行操作了。

查看有几个数据库:show databases;

切换数据库:uses XXX;

查看有哪些表:show collections;(mongo)

7、 进入mongo安装目录的bin,命令行(windows 和 Linux类似)

mongo 127.0.0.1:27017

l  查询:语法:db.collection.find(query, projection);

query:查询条件,projection:返回的键值对,类似于sql中返回的字段。两个参数都可缺省,如都缺省,则返回所有集合中所有数据。如果要返回格式化数据,使用 pretty()

sql语句中简单查询语句中的查询条件and,or,like,in, not in

and:{“key1”:”value1”,”key2”:”value2”},or:{$or:[{“key1”:”value1”},{“key2”:”value2”}]}

like:{“key1”:/value1/},in:{$in:[value1,value2,value3]},not in: in:{$nin:[value1,value2,value3]}

这是and的查询,其他的可自行找资料。再介绍一下projection参数,这个参数用来控制需要返回的键值对,格式为:{key1:1,key2:1} 或者 {key1:0,key2:0}

其实通过这种查询返回的都是游标对象,所以还可以用游标的形式进行遍历。

var cursor = db.envet.find({“key1”:”value1”})

while(cursor.hasNext()) printjson(cursor.next());

这种写法,是javascript shell的方式,还有一种mongo shell,也可以运行游标,这两种对于开发来说,用的非常少,我也不太懂,大家可以自行学习。

还有一种查询db.collection.findOne(),减少了游标操作,只返回一行。

下面看一下mongo常用的操作符如下:

 

写入:db.collection.save(query),与关系型数据库不同的地方是,不需要提前建好集合(关系型数据库:表),在第一次写入时,会自动创建。每个document都会自动创建一个ID(_id),类似于Oracle中的rowid。

8、 java调用mongodb

java调用其实也比较简单,下载对应驱动文件即可。

  • 创建配置文件:mongodb.cfg.properties
#configure threadPool
#Mongodb 数据库地址
mongo.db.address = XXX.XXX.XXX.XXX
#Mongodb 数据库IP
mongo.db.port = 27017
#Mongodb 数据库用户名
mongo.db.username = XXX
#Mongodb 数据库密码
mongo.db.password =
#Mongodb 数据库实例
mongo.db.dbname = XXX
#Mongodb 数据库可以建立的最大连接数
mongo.db.connectionsPerHost=20
#Mongodb 与数据库建立连接的超时时间20mins 20*60*1000
mongo.db.connectTimeout=1200000
#Mongodb 一个线程获取到数据库连接的最大阻塞时间 5mins 5*60*1000
mongo.db.maxWaitTime=300000
#Mongodb 线程队列最大值 注:该值和最大连接数的乘积为线程队列最大值
mongo.db.threadsAllowedToBlockForConnectionMultiplier=10
  • 编写工具类:MongoDbFactory类(单例)
package dnzl.comman.mongodb;

import org.apache.log4j.Logger;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;

import dnzl.server.SystemName;
import dnzl.util.Config;


public class MongoFactory {
    
    private static final Logger LOGGER = Logger.getLogger(MongoFactory.class);

    private static MongoClient mongoClient = null;
    private static String localhost = "";
    private static int port = 0;
    public static String db = "";
    private static int connectinsPerHost = 0;
    private static int connectTimeout = 0;
    private static int threadsAllowedToBlockForConnectionMultiplier = 0;

    static {
        try {
            Config.conf(SystemName.MONGO);
            localhost = Config.getString("mongo.db.address");
            port = Integer.parseInt(Config.getString("mongo.db.port"));
            db = Config.getString("mongo.db.dbname");
            connectinsPerHost = Integer.parseInt(Config.getString("mongo.db.connectionsPerHost"));
            connectTimeout = Integer.parseInt(Config.getString("mongo.db.connectTimeout"));
            threadsAllowedToBlockForConnectionMultiplier = Integer.parseInt(Config.getString("mongo.db.threadsAllowedToBlockForConnectionMultiplier"));
            LOGGER.info("Mongo configure loaded successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取默认数据库连接
     * @return
     */
    public static MongoClient getMongodbInstance() {
        if (mongoClient == null) {
            mongoClient = createMongodb();
        }
        return mongoClient;
    }

    private static MongoClient createMongodb() {
        MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
        builder.connectionsPerHost(connectinsPerHost);
        builder.connectTimeout(connectTimeout);
        builder.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);
        MongoClientOptions myOptions = builder.build();
        // 连接到mongodb
        MongoClient mongoClient = new MongoClient(new ServerAddress(localhost , port),myOptions);
        // 打开数据库
//        MongoDatabase dbInstance = null;
//        dbInstance = mongoClient.getDatabase(db);
        return mongoClient;
    }

    public String toString() {
        StringBuffer strb = new StringBuffer("This MongoDb[");
        strb.append("ip is:" + localhost);
        strb.append(", port is : " + port);
        strb.append(", defaultDB is :" + db +"]");
        return strb.toString();
    }
}
  • 应用:MongoDBDaoImpl.java

 

package dnzl.comman.mongodb.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.bson.Document;
import org.bson.conversions.Bson;

import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;

import dnzl.comman.mongodb.MogoDBOpertions;
import dnzl.comman.mongodb.MongoDBDao;
import dnzl.comman.mongodb.MongoFactory;

public class MongoDBDaoImpl implements MongoDBDao {
    private static final Logger LOGGER = Logger.getLogger(MongoDBDaoImpl.class);

    
    public MongoDBDaoImpl() {
    }

    protected MongoCollection<Document> getCollection(String collectionName) {
        MongoClient mongoClient = MongoFactory.getMongodbInstance();
        MongoDatabase mongodb = mongoClient.getDatabase(MongoFactory.db);
        return mongodb.getCollection(collectionName.toUpperCase());
    }

    @Override
    public boolean inSert(String collectionName, String[] keys, Object[] values) {
        if (keys == null && values == null) {
            return false;
        } else {
            MongoCollection<Document> collection = getCollection(collectionName);
            Document document = new Document();
            for (int i = 0; i < keys.length; i ++) {
                document.append(keys[i], values[i]);
            }
            collection.insertOne(document);
            return true;
        }
    }


    @Override
    public boolean insertMany(String collectionName,
            List<Map<String, Object>> list) {
        MongoCollection<Document> collection = getCollection(collectionName);
        ArrayList<Document> lists = new ArrayList<Document>();
        for (Map<String,Object> map : list) {
            Document doc = new Document();
            doc.putAll(map);
            lists.add(doc);
        }
        try {
            collection.insertMany(lists);
            return true;
        } catch (Exception e) {
            LOGGER.error("Mongo write data exception",e);
            return false;
        }
    }

    @Override
    public boolean delete(String collectionName, String[] keys, Object[] values) {
        if (keys == null && values == null) {
            return false;
        } else {
            MongoCollection<Document> collection = getCollection(collectionName);
            Document document = new Document();
            for (int i = 0 ; i < keys.length; i++) {
                document.append(keys[i], values[i]);
            }
            collection.deleteMany(document);
            return true;
        }
    }
    
    @Override
    public boolean drop(String collectionName) {
        if (collectionName == null || "".equals(collectionName)) {
            return false;
        } else {
            MongoCollection<Document> collection = getCollection(collectionName);
            collection.drop();
            return true;
        }
    }

    @Override
    public List<Document> find(String collectionName, String[] keys,
            Object[] values, String [] res) {
        if (keys == null && values == null) {
            return null;
        } else {
            MongoCollection<Document> collection = getCollection(collectionName);
            ArrayList<Document> lists = new ArrayList<Document>();
            /**
             * 组装查询条件
             */
            Document document = new Document();
            for (int i = 0 ; i < keys.length; i++) {
                document.append(keys[i], values[i]);
            }
            /**
             * 根据查询条件获取所有结果
             */
            FindIterable<Document> findTable = collection.find(document);
            MongoCursor<Document> mCursor = findTable.iterator();
            
            if (res == null || (res.length > 0 && (res[0] == null || "".equals(res[0])))) {
                /**
                 * 如果需要查询的字段为空,则返回全部字段(不包含mongoDB自带的_id字段)
                 */
                Document rdocument = new Document();
                while (mCursor.hasNext()) {
                    Document mc = mCursor.next();
                    for (String key : mc.keySet()) {
                        /**
                         * 剔除_id字段
                         */
                        if ("_id".equals(key)) {
                            continue;
                        }
                        rdocument.append(key, mc.get(key));
                    }
                    lists.add(rdocument);
                }
            } else {
                /**
                 * 组装指定的查询字段
                 */
                int len = res.length;
                while (mCursor.hasNext()) {
                    Document mc = mCursor.next();
                    Document rdocument = new Document();
                    for (int i = 0; i < len; i++) {
                        rdocument.append(res[i], mc.get(res[i]));
                    }
                    lists.add(rdocument);
                }
            }
            return lists;
        }
    }
    public List<Document> find(String collectionName, String[] keys,String [] operations,
            Object[] values, String [] res) {
        if (keys == null && values == null) {
            return null;
        } else {
            if (keys.length != operations.length) {
                return null;
            }
            MongoCollection<Document> collection = getCollection(collectionName);
            ArrayList<Document> lists = new ArrayList<Document>();
            /**
             * 组装查询条件
             */
            ArrayList<Bson> iterable = new ArrayList<Bson>();
            for (int i = 0 ; i < keys.length; i++) {
                if (MogoDBOpertions.isValidOperater(operations[i])) {
                    Bson operator = null;
                    if ("=".equals(operations[i])) {
                        operator = Filters.eq(keys[i], values[i]);
                    } else if (">".equals(operations[i])) {
                        operator = Filters.gt(keys[i], values[i]);
                    } else if (">=".equals(operations[i])) {
                        operator = Filters.gte(keys[i], values[i]);
                    } else if ("!=".equals(operations[i]) || "<>".equals(operations[i])) {
                        operator = Filters.ne(keys[i], values[i]);
                    } else if ("<".equals(operations[i])) {
                        operator = Filters.lt(keys[i], values[i]);
                    } else if ("<=".equals(operations[i])) {
                        operator = Filters.lte(keys[i], values[i]);
                    } else if ("like".equals(operations[i]) || "LIKE".equals(operations[i])){
                        /**
                         *  MongoDB模糊查询
                         *  1、完全匹配:
                         *    ^name$,相当于key='name'
                         *  2、右匹配:
                         *    ^.*name$,相当于key like '%name'
                         *  3、左匹配:
                         *    ^name.*$,相当于key like 'name%'
                         *  4、模糊匹配:
                         *    ^.*name.*$,相当于 key like '%name%'
                         */
                        Pattern pattern = null;
                        if (!String.valueOf(values[i]).startsWith("%") && String.valueOf(values[i]).endsWith("%")) {
                            pattern = Pattern.compile("^"+String.valueOf(values[i]).replace("%", "") + ".*$", Pattern.CASE_INSENSITIVE);
                        } else if (String.valueOf(values[i]).startsWith("%") && !String.valueOf(values[i]).endsWith("%")) {
                            pattern = Pattern.compile("^.*"+String.valueOf(values[i]).replace("%", "") + "$", Pattern.CASE_INSENSITIVE);
                        } else if (String.valueOf(values[i]).startsWith("%") && String.valueOf(values[i]).endsWith("%")) {
                            pattern = Pattern.compile("^.*"+String.valueOf(values[i]).replace("%", "") + ".*$", Pattern.CASE_INSENSITIVE);
                        } else {
                            pattern = Pattern.compile("^"+String.valueOf(values[i]).replace("%", "") + ".*$", Pattern.CASE_INSENSITIVE);
                        } 
                        operator = Filters.regex(keys[i], pattern);
                    } else if("in".equals(operations[i]) || "IN".equals(operations[i])) {
                        Object [] inValue = String.valueOf(values[i]).split(",");
                        operator = Filters.in(keys[i], inValue);
                    }
                    iterable.add(operator);
                } else {
                    LOGGER.info(String.format("invalid operation in condition [%s %s %s]", keys[i],operations[i],values[i]));
                }
            }
            /**
             * 将所有条件拼接为用and连接
             */
            Bson query = Filters.and(iterable);
            /**
             * 根据查询条件获取所有结果
             */
            FindIterable<Document> findTable = collection.find(query);
            MongoCursor<Document> mCursor = findTable.iterator();
            
            if (res == null || (res.length > 0 && (res[0] == null || "".equals(res[0])))) {
                /**
                 * 如果需要查询的字段为空,则返回全部字段(不包含mongoDB自带的_id字段)
                 */
                Document rdocument = new Document();
                while (mCursor.hasNext()) {
                    Document mc = mCursor.next();
                    for (String key : mc.keySet()) {
                        /**
                         * 剔除_id字段
                         */
                        if ("_id".equals(key)) {
                            continue;
                        }
                        rdocument.append(key, mc.get(key));
                    }
                    lists.add(rdocument);
                }
            } else {
                /**
                 * 组装指定的查询字段
                 */
                int len = res.length;
                while (mCursor.hasNext()) {
                    Document mc = mCursor.next();
                    Document rdocument = new Document();
                    for (int i = 0; i < len; i++) {
                        rdocument.append(res[i], mc.get(res[i]));
                    }
                    lists.add(rdocument);
                }
            }
            return lists;
        }
    }
    
    @Override
    public List<Document> find(String collectionName) {
        if (collectionName == null || "".equals(collectionName)) {
            return null;
        } else {
            ArrayList<Document> lists = new ArrayList<Document>();
            MongoCollection<Document> collection = getCollection(collectionName);
            FindIterable<Document> findTable = collection.find();
            MongoCursor<Document> mCursor = findTable.iterator();
            Document rdocument = new Document();
            while (mCursor.hasNext()) {
                Document mc = mCursor.next();
                for (String key : mc.keySet()) {
                    /**
                     * 剔除_id字段
                     */
                    if ("_id".equals(key)) {
                        continue;
                    }
                    rdocument.append(key, mc.get(key));
                }
                lists.add(rdocument);
            }
            return lists;
        }
    }

    @Override
    public boolean update(String collectionName, String conditionKey, Object conditionValue,
            String resultKey, Object resultValue) {
        // TODO Auto-generated method stub
        MongoCollection<Document> collection = getCollection(collectionName);
        collection.updateOne(Filters.eq(conditionKey,conditionValue), new Document("$set",new Document(resultKey, resultValue)));
////        collection.updateMany(arg0, arg1, arg2);
//        UpdateOptions u = new UpdateOptions();
//        u.
        return false;
    }

    @Override
    public boolean isExit(String collectionName, String key, Object value) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void createIndex(String collectionName, String...keys) {
        MongoCollection<Document> collection = getCollection(collectionName);
        Document idoc = new Document();
        int keys_len = keys.length;
        for (int i = 0; i< keys_len; i++) {
            idoc.append(keys[i], 1);
        }
        collection.createIndex(idoc);
    }
}

 

四、MongoDB 分布式集群和分片

MongoDB 支持在多个机器中通过异步复制达到故障转移和实现冗余。 多机器中同一时刻只有一台是用于写操作。 正是由于这个情况, 为 MongoDB 提供了数据一致性的保障。 担当 Primary 角色的机器能把读操作分发给 slave,实现读写分离 。

MongoDB 在 1.6 版本提供了新功能 replica sets(复制集) , 这比之前的 replication 功能要强大一些, 增加了故障自动切换和自动修复成员节点, 各个 DB 之间数据完全一致, 大大降低了维护成功,replica set 故障切换完全自动,实现了高可用。

MongoDB集群节点的增加和删除均支持热部署,节点同步数据简单。

MongoDB分片是将海量的数据水平扩展的数据库集群系统, 数据分表存储在分片的各个节点上, 使用者通过简单的配置就可以很方便地构建一个分布式 MongoDB 集群。

关于集群和分片,我们下次再分享。

posted on 2018-10-22 14:33  谷谷南  阅读(3617)  评论(0编辑  收藏  举报