zoukankan      html  css  js  c++  java
  • MongoDB学习

    MongoDB 连接

    mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
    
    • mongodb:\ 这是固定格式,必须要指定
    • username:password@ 可选 用户名:密码
    • host1 必须指定至少一个host,连接复制集,请指定多个主机地址
    • port 可选指定端口,如果不填,默认 27017
    • /database 如果指定username:password@,连接并验证登陆指定数据库。若不指定,默认打开 test 数据库
    • ?options是连接选项,如果不使用/database,则前面需要加上/。

    MongoDB 连接命令格式

    $ ./mongo
    MongoDB shell version: 4.0.9
    connecting to: test
    

    使用用户 admin 使用密码 123456 连接到本地的 MongoDB 服务上。输出结果如下所示:

    > mongodb://admin:123456@localhost/
    ... 
    
    更多连接实例
    
    连接本地数据库服务器,端口是默认的。
    
    mongodb://localhost
    
    使用用户名fred,密码foobar登录localhost的admin数据库。
    
    mongodb://fred:foobar@localhost
    
    使用用户名fred,密码foobar登录localhost的baz数据库。
    
    mongodb://fred:foobar@localhost/baz
    
    连接 replica pair, 服务器1为example1.com服务器2为example2。
    
    mongodb://example1.com:27017,example2.com:27017
    
    连接 replica set 三台服务器 (端口 27017, 27018, 和27019):
    
    mongodb://localhost,localhost:27018,localhost:27019
    
    连接 replica set 三台服务器, 写入操作应用在主服务器 并且分布查询到从服务器。
    
    mongodb://host1,host2,host3/?slaveOk=true
    
    直接连接第一个服务器,无论是replica set一部分或者主服务器或者从服务器。
    
    mongodb://host1,host2,host3/?connect=direct;slaveOk=true
    
    当你的连接服务器有优先级,还需要列出所有服务器,你可以使用上述连接方式。
    
    安全模式连接到localhost:
    
    mongodb://localhost/?safe=true
    
    以安全模式连接到replica set,并且等待至少两个复制服务器成功写入,超时时间设置为2秒。
    
    mongodb://host1,host2,host3/?safe=true;w=2;wtimeoutMS=2000
    

    MongoDB 创建数据库

    创建数据库
    use DATABASE_NAME
    

    如果数据库不存在,则创建数据库,否则切换到指定数据库

    查看数据库
    db
    
    查看所有数据库
    show dbs
    

    刚创建的数据库并不在全部数据库列表中,如果显示,需要插入数据

    MongoDB 删除数据库

    删除当前数据库
    db.dropDatabase()
    
    删除集合
    db.collection.drop()
    

    以下实例删除了 runoob 数据库中的集合 site:

    > use runoob
    switched to db runoob
    > db.createCollection("runoob")     # 先创建集合,类似数据库中的表
    > show tables
    runoob
    > db.runoob.drop()
    true
    > show tables
    > 
    

    MongoDB 创建集合

    db.createCollection(name,options)
    
    • name:要创建的集合名称
    • options:要选参数,指定有关内存大小及索引的选项

    options 可以是如下参数

    字段 类型 描述
    capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
    autoIndexId 布尔 (可选)如为 true,自动在 _id 字段创建索引。默认为 false。
    size 数值 (可选)为固定集合指定一个最大值(以字节计)。如果 capped 为 true,也需要指定该字段。
    max 数值 (可选)指定固定集合中包含文档的最大数量。

    在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

    创建固定集合 mycol,整个集合空间大小 6142800 KB, 文档最大个数为 10000 个。

    > db.createCollection("mycol", { capped : true, autoIndexId : true, size : 
       6142800, max : 10000 } )
    { "ok" : 1 }
    >
    

    MongoDB 删除集合

    db.collection.drop() # collection是集合名
    

    MongoDB 插入文档

    db.COLLECTION_NAME.inset(document)
    

    以下文档可以存储在 MongoDB 的 runoob 数据库 的 col 集合中:

    >db.col.insert({title: 'MongoDB 教程', 
        description: 'MongoDB 是一个 Nosql 数据库',
        by: '菜鸟教程',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 100
    })
    

    以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

    查看已插入文档:
    以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

    查看已插入文档:
    > db.col.find()
    { "_id" : ObjectId("56064886ade2f21f36b03134"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
    > 
    

    我们也可以将数据定义为一个变量,如下所示:

    > document=({title: 'MongoDB 教程', 
        description: 'MongoDB 是一个 Nosql 数据库',
        by: '菜鸟教程',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 100
    });
    

    插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

    MongoDB 更新文档

    update()方法

    update()方法用于更新已存在的文档

    db.collection.update(
       <query>,
       <update>,
       {
         upsert: <boolean>,
         multi: <boolean>,
         writeConcern: <document>
       }
    )
    

    参数说明:

    • query : update的查询条件,类似sql update查询内where后面的。
    • update : update的对象和一些更新的操作符(如(,)inc...)等,也可以理解为sql update查询内set后面的
    • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
    • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
    • writeConcern :可选,抛出异常的级别。
    save()方法

    save()方法通过传入的文档来代替已有的文档

    db.collection.save(
       <document>,
       {
         writeConcern: <document>
       }
    )
    

    参数说明:

    • document:文档数据
    • writeConcern:可选,抛出异常的级别
    更多实例
    
    只更新第一条记录:
    db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );
    
    全部更新:
    db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );
    
    只添加第一条:
    db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );
    
    全部添加进去:
    db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );
    
    全部更新:
    db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true );
    
    只更新第一条记录:
    db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );
    

    MongoDB 删除文档

    db.collection.remove(
       <query>,
       <justOne>
    )
    
    • query:可选,删除文档的条件
    • justOne:可选,如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档

    MongoDB 查询文档

    db.collection.find(query, projection)
    
    • query :可选,使用查询操作符指定查询条件
    • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

    若不指定 projection,则默认返回所有键,指定 projection 格式如下,有两种模式

    db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的键,不返回其他键
    db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的键,返回其他键
    

    _id 键默认返回,需要主动指定 _id:0 才会隐藏

    两种模式不可混用(因为这样的话无法推断其他键是否应返回)

    db.collection.find(query, {title: 1, by: 0}) // 错误
    

    只能全1或全0,除了在inclusion模式时可以指定_id为0

    db.collection.find(query, {_id:0, title: 1, by: 1}) // 正确
    

    若不想指定查询条件参数 query 可以 用 {} 代替,但是需要指定 projection 参数:

    querydb.collection.find({}, {title: 1})
    

    易读的方式来读取数据

    >db.col.find().pretty()
    

    pretty() 方法以格式化的方式来显示所有文档

    除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档

    操作 格式 范例 RDBMS中的类似语句
    等于 {:} db.col.find({"by":"菜鸟教程"}).pretty() where by = '菜鸟教程'
    小于 {:{$lt:}} db.col.find({"likes":{$lt:50}}).pretty() where likes < 50
    小于或等于 {:{$lte:}} db.col.find({"likes":{$lte:50}}).pretty() where likes <= 50
    大于 {:{$gt:}} db.col.find({"likes":{$gt:50}}).pretty() where likes > 50
    大于或等于 {:{$gte:}} db.col.find({"likes":{$gte:50}}).pretty() where likes >= 50
    不等于 {:{$ne:}} db.col.find({"likes":{$ne:50}}).pretty() where likes != 50
    实例

    如果是 qty 大于 50 小于 80 不能这样写:

    db.posts.find( {  qty: { $gt: 50 }, qty: { $lt: 80 } } )
    

    应该这样:

    db.posts.find( {  qty: { $gt: 50 ,$lt: 80}} )
    

    MongoDB and条件

    MongoDB的find()方法可以传入多个键(key),每个键(key)以逗号隔开,即常规SQL的AND条件

    >db.col.find({key1:value1, key2:value2}).pretty()
    

    AND 和 OR 联合使用

    以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 'where likes>50 AND (by = '菜鸟教程' OR title = 'MongoDB 教程')'

    >db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
    

    MongoDB 条件操作符

    (>) 大于 - $gt  greater than
    (<) 小于 - $lt  gt equal
    (>=) 大于等于 - $gte    less than
    (<=) 小于等于 - $lte    lt equal
    (!=) 不等于 - $ne   not equal
    (=)  等于 - $eq  equal
    
    MongoDB (>) 大于操作符 - $gt

    获取 "col" 集合中 "likes" 大于 100 的数据

    db.col.find({likes : {$gt : 100}})
    
    类似SQL:select * from col where likes >100;
    
    MongoDB(>=)大于等于操作符 - $gte

    获取"col"集合中 "likes" 大于等于 100 的数据

    db.col.find({likes : {$gte : 100}})
    
    类似SQL:select * from col where likes >=100;
    
    MongoDB (<) 小于操作符 - $lt

    获取"col"集合中 "likes" 小于 150 的数据

    db.col.find({likes : {$lt : 150}})
    
    类似SQL:select * from col where likes < 150;
    
    MongoDB (<=) 小于等于操作符 - $lte

    获取"col"集合中 "likes" 小于等于 150 的数据

    db.col.find({likes : {$lte : 150}})
    类似SQL:select * from col where likes <= 150;
    
    MongoDB 使用 (<) 和 (>) 查询 - $lt 和 $gt

    获取"col"集合中 "likes" 大于100,小于 200 的数据

    db.col.find({likes : {$lt :200, $gt : 100}})
    类似SQL:Select * from col where likes>100 AND  likes<200;
    
    模糊查询
    
    查询 title 包含"教"字的文档:
    
    db.col.find({title:/教/})
    
    查询 title 字段以"教"字开头的文档:
    
    db.col.find({title:/^教/})
    
    查询 titl e字段以"教"字结尾的文档:
    
    db.col.find({title:/教$/})
    

    MongoDB $type 操作符

    $type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。

    类型 数字 备注
    Double 1
    String 2
    Object 3
    Array 4
    Binary data 5
    Undefined 6 已废弃。
    Object id 7
    Boolean 8
    Date 9
    Null 10
    Regular Expression 11
    JavaScript 13
    Symbol 14
    JavaScript (with scope) 15
    32-bit integer 16
    Timestamp 17
    64-bit integer 18
    Min key 255 Query with -1.
    Max key 127

    如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:

    db.col.find({"title" : {$type : 2}})
    或
    db.col.find({"title" : {$type : 'string'}})
    

    MongoDB Limit与Skip方法

    limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

    >db.COLLECTION_NAME.find().limit(NUMBER)
    

    除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

    >db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
    
    笔记
    db.col.find({},{"title":1,_id:0}).limit(2)
    
    • 第一个 {} 放 where 条件,为空表示返回集合中所有文档。
    • 第二个 {} 指定那些列显示和不显示 (0表示不显示 1表示显示)。

    > db.COLLECTION_NAME.find().skip(10).limit(100)
    

    以上实例在集合中跳过前面 10 条返回 100 条数据。

    skip 和 limit 结合就能实现分页。

    skip和limit方法只适合小数据量分页,如果是百万级效率就会非常低,因为skip方法是一条条数据数过去的,建议使用where_limit

    在查看了一些资料之后,发现所有的资料都是这样说的:

    不要轻易使用Skip来做查询,否则数据量大了就会导致性能急剧下降,这是因为Skip是一条一条的数过来的,多了自然就慢了。

    这么说Skip就要避免使用了,那么如何避免呢?首先来回顾SQL分页的后一种时间戳分页方案,这种利用字段的有序性质,利用查询来取数据的方式,可以直接避免掉了大量的数数。也就是说,如果能附带上这样的条件那查询效率就会提高,事实上是这样的么?我们来验证一下:

    这里我们假设查询第100001条数据,这条数据的Amount值是:2399927,我们来写两条语句分别如下:

    b.test.sort({"amount":1}).skip(100000).limit(10)  //183ms
    db.test.find({amount:{$gt:2399927}}).sort({"amount":1}).limit(10)  //53ms
    

    结果已经附带到注释了,很明显后者的性能是前者的三分之一,差距是非常大的。也印证了Skip效率差的理论。


    limit(n) 是用来规定显示的条数,而 skip(n) 是用来在符合条件的记录中从第一个记录跳过的条数,这两个函数可以交换使用。

    比如:find({},{age:1,_id:0}).limit(2).skip(1),在符合条件的文档中,要显示两条文档,显示的位置从跳过第一条记录开始。这样不是很好理解。

    如果写成 find({},{age:1,_id:0}).skip(1).limit(2),在符合条件的文档中,先跳过第一条文档,然后显示两条文档,这样比较好理解。


    MongoDB 排序

    sort 1 为升序 -1 是降序

    >db.COLLECTION_NAME.find().sort({KEY:1})
    

    MongoDB 索引

    createIndex() 创建索引

    >db.collection.createIndex(keys, options)
    
    • Key 创建的索引字段
    • 1 为指定按升序创建索引 -1 降序
    实例
    >db.col.createIndex({"title":1,"description":-1})
    

    MongoDB 聚合

    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。

    >db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
    
    表达式 描述 实例
    $sum 计算总和。 db.mycol.aggregate([{(group : {_id : ")by_user", num_tutorial : {(sum : ")likes"}}}])
    $avg 计算平均值 db.mycol.aggregate([{(group : {_id : ")by_user", num_tutorial : {(avg : ")likes"}}}])
    $min 获取集合中所有文档对应值得最小值。 db.mycol.aggregate([{(group : {_id : ")by_user", num_tutorial : {(min : ")likes"}}}])
    $max 获取集合中所有文档对应值得最大值。 db.mycol.aggregate([{(group : {_id : ")by_user", num_tutorial : {(max : ")likes"}}}])
    $push 在结果文档中插入值到一个数组中。 db.mycol.aggregate([{(group : {_id : ")by_user", url : {(push: ")url"}}}])
    $addToSet 在结果文档中插入值到一个数组中,但不创建副本。 db.mycol.aggregate([{(group : {_id : ")by_user", url : {(addToSet : ")url"}}}])
    $first 根据资源文档的排序获取第一个文档数据。 db.mycol.aggregate([{(group : {_id : ")by_user", first_url : {(first : ")url"}}}])
    $last 根据资源文档的排序获取最后一个文档数据 db.mycol.aggregate([{(group : {_id : ")by_user", last_url : {(last : ")url"}}}])
    实例

    计算每个作者所写的文章数,使用aggregate()计算结果如下:

    > db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])
    {
       "result" : [
          {
             "_id" : "runoob.com",
             "num_tutorial" : 2
          },
          {
             "_id" : "Neo4j",
             "num_tutorial" : 1
          }
       ],
       "ok" : 1
    }
    >
    

    类似sql

     select by_user, count(*) from mycol group by by_user
    

    管道的概念

    管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。

    MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

    表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

    这里我们介绍一下聚合框架中常用的几个操作:

    • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
    • (match:用于过滤数据,只输出符合条件的文档。)match使用MongoDB的标准查询操作。
    • $limit:用来限制MongoDB聚合管道返回的文档数。
    • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
    • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
    • $group:将集合中的文档分组,可用于统计结果。
    • $sort:将输入文档排序后输出。
    • $geoNear:输出接近某一地理位置的有序文档。
    管道操作符实例

    1、$project实例

    db.article.aggregate(
        { $project : {
            title : 1 ,
            author : 1 ,
        }}
     );
    

    这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:

    db.article.aggregate(
       { $project : {
           _id : 0 ,
           title : 1 ,
           author : 1
       }});
    

    2.$match实例

    db.articles.aggregate( [
                            { $match : { score : { $gt : 70, $lte : 90 } } },
                            { $group: { _id: null, count: { $sum: 1 } } }
                           ] );
    

    (match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段)group管道操作符进行处理。


    3.$skip实例

    db.article.aggregate(
        { $skip : 5 });
    

    经过$skip管道操作符处理后,前五个文档被"过滤"掉。


    按日、按月、按年、按周、按小时、按分钟聚合操作如下:

    db.getCollection('m_msg_tb').aggregate(
    [
        {$match:{m_id:10001,mark_time:{$gt:new Date(2017,8,0)}}},
        {$group: {
           _id: {$dayOfMonth:'$mark_time'},
            pv: {$sum: 1}
            }
        },
        {$sort: {"_id": 1}}
    ])
    

    时间关键字如下:

    • $dayOfYear: 返回该日期是这一年的第几天(全年 366 天)。
    • $dayOfMonth: 返回该日期是这一个月的第几天(1到31)。
    • $dayOfWeek: 返回的是这个周的星期几(1:星期日,7:星期六)。
    • $year: 返回该日期的年份部分。
    • $month: 返回该日期的月份部分( 1 到 12)。
    • $week: 返回该日期是所在年的第几个星期( 0 到 53)。
    • $hour: 返回该日期的小时部分。
    • $minute: 返回该日期的分钟部分。
    • $second: 返回该日期的秒部分(以0到59之间的数字形式返回日期的第二部分,但可以是60来计算闰秒)。
    • $millisecond:返回该日期的毫秒部分( 0 到 999)。
    • $dateToString: { $dateToString: { format: , date: } }。

    参考链接


    MongoDB 复制(副本集)

    MongoDB复制是将数据同步在多个服务器的过程。
    MongoDB复制至少需要两个节点。常见搭配:一主一从、一主多从
    主节点记录所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

    MongoDB副本集设置
    mongod --port "PORT" --dbpath "YOUR_DB_DATA_PATH" --replSet "REPLICA_SET_INSTANCE_NAME"
    
    实例
    mongod --port 27017 --dbpath "D:set upmongodbdata" --replSet rs0
    

    启动一个名为rs0的MongoDB实例,其端口号为27017。

    在Mongo客户端使用命令rs.initiate()来启动一个新的副本集。

    我们可以使用rs.conf()来查看副本集的配置

    查看副本集状态使用 rs.status() 命令


    副本集添加成员
    >rs.add(HOST_NAME:PORT)
    

    MongoDB中你只能通过主节点将Mongo服务添加到副本集中, 判断当前运行的Mongo服务是否为主节点可以使用命令db.isMaster()

    MongoDB的副本集与我们常见的主从有所不同,主从在主机宕机后所有服务将停止,而副本集在主机宕机后,副本会接管主节点成为主节点,不会出现宕机的情况。

  • 相关阅读:
    VRChat简易教程1-开发环境准备(SDK)
    BeatSaber节奏光剑插件开发官方教程2-简单的插件示例
    BeatSaber节奏光剑插件开发官方教程1-创建一个插件模板
    BeatSaber节奏光剑双手柄MR教程
    第四章 HTML与JavaScript
    第二章数据和判定
    蓝港在线笔试经验
    数据结构总复习(查找)
    数据结构总复习(3)
    数据结构总复习(2)
  • 原文地址:https://www.cnblogs.com/niuben/p/11250357.html
Copyright © 2011-2022 走看看