您的位置:首页 > 数据库 > Mongodb

MongoDB学习(一):安装&基础概念&数据类型&部分shell操作

2019-01-15 20:01 411 查看

MongoDB安装

环境:WSL Ubuntu 18.04 LTS

安装的版本为:3.6.9

1. 导入公钥

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5

2. 创建源列表文件MongoDB

在/etc/apt/sources.list.d/中创建一个MongoDB列表文件:

echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list

3. 更新存储库

sudo apt-get update

4. 安装MongoDB

sudo apt-get install -y mongodb-org

5. 启动MongoDB:

因为WSL不支持systemctl start,只好开两个窗口,一个使用mongod命令启动服务端,一个使用mongo命令启动客户端的Mongo Shell

上图左侧为服务端,右侧为客户端,可以看到客户端连接成功后,服务端输出了客户端信息

基本概念

  • 主键:和MySQL含义相同,默认会创建一个"_id"字段,类型为ObjectId
  • 域:相当于MySQL中的表的一列
  • 文档:键值对形式,bson格式,相当于MySQL中的表的一行 [ul]键不能包含'\0';
  • ‘.’和'$'有特殊意义,'_'开头的名称为保留名
  • 名称大小写敏感
  • 键值对有序,顺序颠倒后是不同的文档
  • 每一个文档的字段不需要完全一致,相同字段值的数据类型也不需要保持一致
  • 文档的键是字符串,每个文档内,键不能重复
  • 文档可以作为值嵌套到其他文档里
  • 集合:一组文档,相当于MySQL中的表
      集合名不能为空,不能包含'\0',不能以"system."开头,不能包含'$'
    • 用'.'分隔不同命名空间的子集合
  • 数据库:和MySQL中定义一致,由0到多个集合组成
      名称不为空,不能包含特殊字符(如:'.'、'/'、'\'、'$'、'\0')
    • 名称区分大小写,应全部小写,名称长度最多64字节
    • 保留名:admin、local、config,这些数据库默认存在
  • 复制集:由一个Primary节点、多个Secondary节点及可选的Arbiter节点组成,即一主多从配置,用于保证高可用
  • 分片集:通过分片构成集群,保证高扩展性
      由如下三个组件构成: shard:数据节点,每一个数据节点存储一部分分片数据,每个shard都可以做复制集
    • mongos:陆游节点,作为客户端和分片集群间的查询路由
    • config server:配置节点,存储集群的元数据和配置信息
  • 支持两种数据分布策略:
      范围分片:将shard key在某个范围内的分片划分在一起,可以很好地满足范围查询,但是如果shard key有明显的递增or递减趋势,就会导致数据过度集中
    • 哈希分片:根据shard key计算hash值,然后再按照范围分片策略进行分布,均衡性更好,但是范围查询不够高效
    [/ul]
  • 存储引擎:MongoDB有三种引擎,可通过 mongod --storageEngine <engineName>命令设置
      MMAPv1:3.2版本之前的默认引擎,简单的内存映射文件,支持集合级别的病发控制,不支持压缩
    • WiredTiger:3.0版本引入的新引擎,3.2版本起的默认引擎,提供文档级病发控制、检查点、数据压缩、本地数据加密等功能
    • In-Memory:将数据仅存储在内存中,只将少量元数据和诊断日志持久化,因此延迟很低。支持文档级别并发控制,用于64位企业版本

    数据类型

    常用的数据类型如下:

    1.ObjectId:12字节长度,标识唯一主键

    其前4个字节为UNIX时间戳(UTC),5~7字节为机器码(标识MongoDB所在机器不同),8~9字节为PID(标识相同机器上不同的MongoDB进程实例),最后三个字节为随机数计数器

    借用菜鸟教程的图:

    2.字符串:只有UTF-8编码的字符串才合法

    3.整型:根据操作系统实现,有4字节或8字节长度两种

    4.布尔值:true和false两种

    5.浮点数:双精度,即double类型

    6.数组:将多个值合并为一个序列,用中括号“[]"包裹起来

    7.时间戳:8字节长度,前4字节是一个time_t值,后4字节是一个秒级计数器

    8.Null:顾名思义,代表空值

    9.Object:内嵌文档类型

    12.正则表达式

    13.二进制类型:存储为禁止数据

    14.日期:ISODate(……)形式,如:ISODate("2019-01-15T20:00:00.000+08:00")

    如果使用new Date(),返回的是时间戳形式,new Date().toString()或Date()返回的是上面的形式

    Shell操作:远程连接、新建数据库&集合并插入数据

    在终端使用 mongo 命令启动Mongo Shell,即可自动连接到本地服务器

    如果要连接远程服务器,有两种方式:

    • 使用 mongo --host <hostname> --port <port> -u <username> -p <password> 命令启动Shell
    • 进入本地Shell后,输入以下命令:
    [code]mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

    用户名、密码不是必须的,port如果是默认的27017,也可以忽略

    options可选如下:

    选项

    描述

    replicaSet=name

    验证replica set的名称。 Impliesconnect=replicaSet.

    slaveOk=true|false

    • true:在connect=direct模式下,驱动会连接第一台机器,即使这台服务器不是主。在connect=replicaSet模式下,驱动会发送所有的写请求到主并且把读取操作分布在其他从服务器。
    • false: 在 connect=direct模式下,驱动会自动找寻主服务器. 在connect=replicaSet 模式下,驱动仅仅连接主服务器,并且所有的读写命令都连接到主服务器。

    safe=true|false

    false: 在每次更新之后,驱动不会发送getLastError来确保更新成功。

    • true: 在执行更新操作之后,驱动都会发送getLastError命令来确保更新成功。(还要参考 wtimeoutMS).

    w=n

    驱动添加 { w : n } 到getLastError命令. 应用于safe=true。

    wtimeoutMS=ms

    驱动添加 { wtimeout : ms } 到 getlasterror 命令. 应用于 safe=true.

    fsync=true|false

    • true: 驱动添加 { fsync : true } 到 getlasterror 命令.应用于 safe=true.
    • false: 驱动不会添加到getLastError命令中。

    journal=true|false

    如果设置为 true, 同步到 journal (在提交到数据库前写入到实体中). 应用于 safe=true

    connectTimeoutMS=ms

    可以打开连接的时间。

    socketTimeoutMS=ms

    发送和接受sockets的时间。

    启动之后,使用命令查看默认的数据库:

    [code]> show dbs
    admin   0.000GB
    config  0.000GB
    local   0.000GB

    这三个就是“基本概念”中提到的保留数据库

    接下来新建一个test数据库:

    [code]> use test
    switched to db test

    如果test已存在,则切换过去,不存在就会新建一个,但是再次show dbs,是看不到空数据库的,需要先插入数据:

    [code]> show dbs
    admin   0.000GB
    config  0.000GB
    local   0.000GB
    > db.user.insert({"username":"zhangsan","sex":"man","age":20,"hobby":"programming"})
    WriteResult({ "nInserted" : 1 })
    > show dbs
    admin   0.000GB
    config  0.000GB
    local   0.000GB
    test    0.000GB

    这样就在test数据库中,自动创建了一个user集合,并插入一个文档

    类似作用的还有insertOne(仅插入一条数据)和insertMany(接受一个数组作为参数,批量插入数据)两个函数

    如果只想创建集合而不插入数据,可以使用:db.createCollection(collection_name, options) 命令,其中options可选:

    字段

    类型

    描述

    capped

    布尔

    (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。

    当该值为 true 时,必须指定 size 参数。

    autoIndexId

    布尔

    (可选)如为 true,自动在 _id 字段创建索引。默认为 false。

    size

    数值

    (可选)为固定集合指定一个最大值(以字节计)。

    如果 capped 为 true,也需要指定该字段。

    max

    数值

    (可选)指定固定集合中包含文档的最大数量。

    如果设置了capped为true,建立的就是固定集合:

    固定集合,顾名思义就是固定大小的集合。它有着很高的性能以及FIFO策略过期的特性。固定集合中文档是按插入顺序保存到集合中,并且这些文档在磁盘上存放位置也是按照插入顺序的,只要数据量不超出size值,文档的位置就固定不变。指定的存储大小包含了数据库的头信息,即实际存储的数据量小于给定的size值。

    • 可以向固定集合添加新的对象。
    • 可以修改固定集合中的值,但是必须确保新值的大小不超过原始值
    • 不能删除某个文档,只能删除整个集合

    删除数据库命令为:db.dropDatabase()

    删除集合命令为:db.collection_name.drop()  collection_name是要删除的集合名称

    查看集合的命令为:show collections

    查看数据库or集合的统计信息,可以用stats()函数

    所有的命令都可以通过help()函数来查询,例如Shell的命令有:

    [code]> help
    db.help()                    help on db methods
    db.mycoll.help()             help on collection methods
    sh.help()                    sharding helpers
    rs.help()                    replica set helpers
    help admin                   administrative help
    help connect                 connecting to a db help
    help keys                    key shortcuts
    help misc                    misc things to know
    help mr                      mapreduce
    
    show dbs                     show database names
    show collections             show collections in current database
    show users                   show users in current database
    show profile                 show most recent system.profile entries with time >= 1ms
    show logs                    show the accessible logger names
    show log [name]              prints out the last segment of log in memory, 'global' is default
    use <db_name>                set current database
    db.foo.find()                list objects in collection foo
    db.foo.find( { a : 1 } )     list objects in foo where a == 1
    it                           result of the last line evaluated; use to further iterate
    DBQuery.shellBatchSize = x   set default number of items to display on shell
    exit                         quit the mongo shell

    db.help()就是显示数据库一级的命令,db.collection_name.help()就是显示文档一级的命令

    绝大部分命令都可以通过db.runCommand()函数来调用,例如db.stats()和db.runCommand({dbstats:1})是等价的

    和Linux Shell一样,MongoDB Shell也支持双击Tab键显示输入提示:

    [code]> db.numbers.get
    db.numbers.getCollection(          db.numbers.getIndexes(             db.numbers.getQueryOptions(
    db.numbers.getDB(                  db.numbers.getIndices(             db.numbers.getShardDistribution(
    db.numbers.getDiskStorageStats(    db.numbers.getMongo(               db.numbers.getShardVersion(
    db.numbers.getFullName(            db.numbers.getName(                db.numbers.getSlaveOk(
    db.numbers.getIndexKeys(           db.numbers.getPagesInRAM(          db.numbers.getSplitKeysForChunks(
    db.numbers.getIndexSpecs(          db.numbers.getPlanCache(           db.numbers.getWriteConcern(
    > db.numbers.get

    输入函数全限定名可以打印函数内容,从而查询每个函数具体接受什么参数,也可以用这种方法实现自己的函数:

    [code]> db.user.find
    function (query, fields, limit, skip, batchSize, options) {
    var cursor = new DBQuery(this._mongo,
    this._db,
    this,
    this._fullName,
    this._massageObject(query),
    fields,
    limit,
    skip,
    batchSize,
    options || this.getQueryOptions());
    
    {
    const session = this.getDB().getSession();
    
    const readPreference = session._serverSession.client.getReadPreference(session);
    if (readPreference !== null) {
    cursor.readPref(readPreference.mode, readPreference.tags);
    }
    
    const readConcern = session._serverSession.client.getReadConcern(session);
    if (readConcern !== null) {
    cursor.readConcern(readConcern.level);
    }
    }
    
    return cursor;
    }
    > db.user.doSomething = function(){ print("Hello") }
    function (){ print("Hello") }
    > db.user.doSomething()
    Hello

    在这里实现了一个doSomething函数,调用之后可以打印Hello,但是这个自定义函数是临时的,重新连接后就会消失

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐