【编程不良人】MongoDB最新实战教程学习笔记

简介

视频链接:01.简介和历史_哔哩哔哩_bilibili

注意:整个课程大部分都来自菜鸟教程,可以直接在菜鸟教程中结果实例学习即可,有针对性薛学习。 

说明

  • 官方

    MongoDB是一个文档数据库,旨在方便应用开发和扩展。

  • 百度百科

        MongoDB是一个基于分布式文件存储的数据库(支持集群、分片处理)。由C++语言编写。旨在为WEB应用提供可扩展高性能的数据存储解决方案

       MongoDB是一个介于关系数据库和非关系数据库之间的产品(偏向于非关系型数据库NoSQL),是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式(对json进行扩展),因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引

       总结: mongoDB是一个非关系型文档数据库。

历史

  • 2009年2月,MongoDB数据库首次在数据库领域亮相,打破了关系型数据库一统天下的局面;

  • 2010年8月, MongoDB 1.6发布。这个版本最大的一个功能就是Sharding---自动分片;

  • 2014年12月, MongoDB 3.0发布。由于收购了WiredTiger 存储引擎,大幅提升了MongoDB的写入性能;

  • 2015年12月,3.2版本发布,开始支持了关系型数据库的核心功能:关联。你可以一次同时查询多个MongoDB的集合。

  • 2016年, MongoDB推出Atlas,在AWS、 Azure 和GCP上的MongoDB托管服务;

  • 2017年10月,MongoDB成功在纳斯达克敲钟,成为26年来第一家以数据库产品为主要业务的上市公司。

  • 2018年6月, MongoDB4.0 发布推出ACID事务支持,成为第一个支持强事务的NoSQL数据库;

  • 2018年--至今,MongoDB已经从一个在数据库领域籍籍无名的“小透明”,变成了话题度和热度都很高的“流量”数据库。

特点

视频链接:02.特点&应用场景_哔哩哔哩_bilibili

特点

  • 面向集合存储,易存储对象类型的数据

  • 支持查询以及动态查询

  • 支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言

  • 文件存储格式为BSON(一种JSON的扩展)

  • 支持复制和故障恢复和分片

  • 支持事务支持(要求性不高,不能完全取代关系型数据库)

  • 索引、聚合、关联....

应用场景

  • 游戏应用:使用云数据库MongoDB作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便进行查询与更新。

  • 物流应用:使用云数据库MongoDB存储订单信息,订单状态在运送过程中会不断更新,以云数据库MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。

  • 社交应用:使用云数据库MongoDB存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且,云数据库MongoDB非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并在写入和读取方面都相对较快。

  • 视频直播:使用云数据库MongoDB存储用户信息、礼物信息等。

  • 大数据应用:使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。

安装

视频链接:03.传统方式安装_哔哩哔哩_bilibili

传统方式

 # 1.下载 MongoDB
 - https://www.mongodb.com/try/download/community

 # 2.将下载安装包上传到 linux 系统
 - tar -zxf mongodb-linux-aarch64-ubuntu2004-5.0.5.tgz 

 # 3.查看安装目录
 - ls
     `bin`目录   用来存放启动mongoDB的服务以及客户端链接的脚本文件等

 # 4.启动 MongoDB 服务
 - ./mongod --port=27017 --dbpath=../data --logpath=../logs/mongo.log
     `--port`    指定服务监听端口号 默认为 27017
     `--dbpath`  指定 mongodb 数据存放目录 启动要求目录必须存在
     `--logpath` 指定 mongodb 日志文件存放位置

注意: 由于指定日志文件因此启动时日志输出到日志中终端不显示任何日志

 # 5.客户端连接
 - ./mongo --port=27017

Docker方式

视频链接:04.Docker 方式安装_哔哩哔哩_bilibili

 # 1.拉取 mongodb 镜像
 - docker pull mongo:5.0.5

 # 2.运行 mongo 镜像
 - docker run -d --name mongo --p 27017:27017 mongo:5.0.5

 # 3.进入 mongo 容器
 - docker exec -it bc6c bash

Windows安装方式

核心概念

视频链接:05.核心概念(库、集合、文档)_哔哩哔哩_bilibili

库<DataBase>

   mongodb中的库就类似于传统关系型数据库中库的概念,用来通过不同库隔离不同应用数据。   

        mongodb中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为"test",数据库存储在启动指定的data目录中。

集合<Collection>

  集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表的概念

       集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

文档<Document>

       文档集合中一条条记录,是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

一个简单的文档例子如下:

 {"site":"www.baizhiedu.xin", "name":"编程不良人"}

关系总结

RDBMSMongoDB
数据库<database>数据库<database>
表<table>集合<collection>
行<row>文档<document>
列<colume>字段<field>

基本操作

视频链接:06.库的相关操作_哔哩哔哩_bilibili

库<database>

  • 查看所有库

     > show databases; | show dbs;

     注意:

    • admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。

    • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合。

    • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

  • 创建数据库

     > use 库名
    

    注意: use 代表创建并使用,当库中没有数据时默认不显示这个库

  • 删除数据库

    • 默认删除当前选中的库

     > db.dropDatabase() ---注意此处有括号

  • 查看当前所在库

     > db;

集合<Collection>

视频链接:07.集合的相关操作_哔哩哔哩_bilibili

  • 查看库中所有集合

     > show collections; | show tables;

  • 创建集合

     > db.createCollection('集合名称', [options])

    options可以是如下参数:

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

注意:当集合不存在时,向集合中插入文档也会自动创建该集合。

  • 删除集合

     > db.集合名称.drop();
     -- 如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

文档<document>

视频链接:08.文档的添加、查询_哔哩哔哩_bilibili

参考文档: mongosh Methods — MongoDB Manual

  • 插入文档

    • 单条文档

       > db.集合名称.insert(document)
       -- 举例:
       > db.users.insert({"name":"编程不良人","age":23,"bir":"2012-12-12"});
       ​
       -- db.集合名称.insertOne():向指定集合中插入一条文档数据【推荐使用】
       > db.users.insertOne({"name":"编程不良人","age":23,"bir":"2012-12-12"});
    • 多条文档

       -- db.collection.insertMany():向指定集合中插入多条文档数据【推荐使用】
       > db.集合名称.insertMany(
          [ <document 1> , <document 2>, ... ],
          {
             writeConcern: 1,//写入策略,默认为1,即要求确认写操作,0是不要求。
             ordered: true //指定是否按顺序写入,默认true,按顺序写入。
          }
       )
       -- 举例:
       > db.users.insert([
           {"name":"不良人","age":23,"bir":"2012-12-12"},
           {"name":"小黑","age":25,"bir":"2012-12-12"}
       ]);
       或
       > db.users.insertMany([
           {"name":"不良人","age":23,"bir":"2012-12-12"},
           {"name":"小黑","age":25,"bir":"2012-12-12"}
       ]);
    • 脚本方式

       for(let i=0;i<100;i++){
           db.users.insert({"_id":i,"name":"编程不良人_"+i,"age":23});
       }
       ​
       -- 1、先创建数组
       -- 2、将数据放在数组中
       -- 3、一次 insert 到集合中
       var arr = [];
       for(var i=1 ; i<=20000 ; i++){
           arr.push({num:i});
       }
       db.numbers.insert(arr);

    注意:在mongodb中每个文档都会有一个_id作为唯一标识,_id默认会自动生成,如果手动指定将使用手动指定的值作为_id 的值。

  • 查询所有

     > db.集合名称.find();

视频链接:09.文档的删除_哔哩哔哩_bilibili

  • 删除文档

     db.集合名称.remove(
        <query>,
        {
          justOne: <boolean>,
          writeConcern: <document>
        }
     )
     -- 由于remove()方法已经过时了,现在官方推荐使用deleteOne()和deleteMany()方法。
     -- db.集合名称.deleteMany({query})  -- 不指定条件时删除集合下全部文档
     > db.users.deleteMany({});
     > db.users.deleteMany({age:23});
     ​
     -- db.集合名称.deleteOne({query})  -- 删除一条文档
     > db.users.deleteOne({_id:ObjectId("64108c960d0d9fdb638f66d0")});

    参数说明:

    • query :可选删除的文档的条件。

    • justOne : 可选如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。

    • writeConcern :可选抛出异常的级别。

注意:文档内容全部删除后,文档仍存在,即删除内容,不删除结构。

视频链接:10.文档的更新_哔哩哔哩_bilibili

MongoDB 更新文档 | 菜鸟教程

  • 更新文档

     db.集合名称.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 :可选,抛出异常的级别。

      • WriteConcern.NONE:没有异常抛出

      • WriteConcern.NORMAL:仅抛出网络错误异常,没有服务器错误异常

      • WriteConcern.SAFE:抛出网络错误异常、服务器错误异常;并等待服务器完成写操作。

      • WriteConcern.MAJORITY: 抛出网络错误异常、服务器错误异常;并等待一个主服务器完成写操作。

      • WriteConcern.FSYNC_SAFE: 抛出网络错误异常、服务器错误异常;写操作等待服务器将数据刷新到磁盘。

      • WriteConcern.JOURNAL_SAFE:抛出网络错误异常、服务器错误异常;写操作等待服务器提交到磁盘的日志文件。

      • WriteConcern.REPLICAS_SAFE:抛出网络错误异常、服务器错误异常;等待至少2台服务器完成写操作。

     - db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()}) 
         `这个更新是将符合条件的全部更新成后面的文档,相当于先删除在更新`
     - db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming"}})
         `保留原来数据更新,但是只更新符合条件的第一条数据`
     - db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true})       
         `保留原来数据更新,更新符合条件的所有数据`
     - db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true,upsert:true})
         `保留原来数据更新,更新符合条件的所有数据,没有条件符合时插入数据

在3.2版本开始,MongoDB提供以下更新集合文档的方法:

  • db.collection.updateOne():向指定集合更新单个文档

    • db.users.updateOne({"_id":0},{$set:{"name":"小呆呆"}})

    • db.users.updateOne({"_id":10},{$set:{"name":"熊大"}},{upsert:true});

  • db.collection.updateMany():向指定集合更新多个文档

    • db.users.updateMany({"name":"小崔加油"},{$set:{"name":"欧力给"}});

文档查询

视频链接:11.文档的查询(一)_哔哩哔哩_bilibili

MongoDB 查询文档 | 菜鸟教程

MongoDB 查询文档使用 find() 方法。find() 方法以非结构化的方式来显示所有文档。

语法

 > db.集合名称.find(query, projection)
  • query :可选,使用查询操作符指定查询条件

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

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

 > db.集合名称.find().pretty()

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

对比语法

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

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

AND

 > db.集合名称.find({key1:value1, key2:value2,...}).pretty()

类似于 WHERE 语句:WHERE key1=value1 AND key2=value2

  • db.users.find({"age":27,"name":"欧力给",_id:8});

  • db.users.find({"age":3,"age":27});同一字段多次出现查询条件时,只有最后的查询条件才生效,即后面会覆盖前面的查询条件

OR

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

 > db.集合名称.find({$or: [{key1: value1}, {key2:value2}]}).pretty()

类似于 WHERE 语句:WHERE key1=value1 or key2=value2

  • db.users.find({$or:[{_id:3},{age:15}]});

视频链接:12.文档的查询(二)_哔哩哔哩_bilibili

AND 和 OR 联合

类似SQL语句为:'where age >50 AND (name = '编程不良人' OR name = 'MongoDB')'

 > db.集合名称.find({"age": {$gt:50}, $or: [{"name": "编程不良人"},{"name": "MongoDB"}]}).pretty();
  • db.users.find({age:{$gt:15},$or:[{_id:3},{age:15}]});

数组中查询

 -- 测试数据
 > db.集合名称.insert({ "_id" : 11, "age" : 29, "likes" : [ "看电视", "读书xx", "美女" ], "name" : "不良人_xx_11" })
 -- 执行数组查询
 > db.users.find({likes:"看电视"})
 -- $size 按照数组长度查询
 > db.users.find({likes:{$size:3}});

模糊查询

类似 SQL 中为 'where name like '%name%''

 > db.users.find({likes:/良/});

注意:在 mongoDB 中使用正则表达式可以是实现近似模糊查询功能

排序

视频链接:13.文档的查询(三)_哔哩哔哩_bilibili

 > db.集合名称.find().sort({name:1,age:1}),
 - 1 升序  -1 降序

类似 SQL 语句为: 'order by name,age'

分页

 > db.集合名称.find().sort({条件}).skip(start).limit(rows);

类似于 SQL 语句为: 'limit start,rows'

总条数

 > db.集合名称.count();
 > db.集合名称.find({"name":"编程不良人"}).count();

类似于 SQL 语句为: 'select count(id) from ....'

DeprecationWarning: Collection.count() is deprecated. Use countDocuments or estimatedDocumentCount.

  • db.users.countDocuments();

  • db.users.estimatedDocumentCount();

去重

 > db.集合名称.distinct('字段')

类似于 SQL 语句为: 'select distinct name from ....'

  • db.users.distinct("age");

指定返回字段

 > db.集合名称.find({条件},{name:1,age:1}) 
 - 参数2: 1 返回  0 不返回    
  • db.users.find({},{"name":1});查询所有,返回指定字段

  • db.users.find({age:{$lt:17}},{name:1});按照指定条件查询,返回指定字段

  • db.users.find({age:{$lt:17}},{_id:0,name:1});按照指定条件查询,返回指定字段,不返回id,注意id是唯一索引

$type

视频链接:14.$type操作符_哔哩哔哩_bilibili

说明

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

MongoDB 中可以使用的类型如下表所示:

类型数字备注
Double1
String2
Object3
Array4
Binary data5
Undefined6已废弃。
Object id7
Boolean8
Date9
Null10
Regular Expression11
JavaScript13
Symbol14
JavaScript (with scope)15
32-bit integer16
Timestamp17
64-bit integer18
Min key255Query with -1.
Max key127

使用

 > db.col.insert({
     title: 'PHP 教程', 
     description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
     by: '编程不良人',
     url: 'http://www.baizhiedu.xin',
     tags: ['php'],
     likes: 200
 });
 ​
 > db.col.insert({
     title: 'Java 教程', 
     description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
     by: '编程不良人',
     url: 'http://www.baizhiedu.xin',
     tags: ['java'],
     likes: 550
 });
 ​
 > db.col.insert({
     title: 'MongoDB 教程', 
     description: 'MongoDB 是一个 Nosql 数据库',
     by: '编程不良人',
     url: 'http://www.baizhiedu.xin',
     tags: ['mongodb'],
     likes: 100
 });
 ​
 > db.col.insert({
     title: 2233, 
     description: '2233 是一个 B站的',
     by: '编程不良人',
     url: 'http://www.baizhiedu.xin',
     tags: ['2233'],
     likes: 100
 });
  • 如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:

 db.col.find({"title" : {$type : 2}}).pretty();
 或
 db.col.find({"title" : {$type : 'string'}}).pretty();
  • 如果想获取 "col" 集合中 tags 为 Array 的数据,你可以使用以下命令:

 db.col.find({"tags":{$type : 4}}).pretty();
 或
 db.col.find({"tags" : {$type : 'array'}}).pretty();

索引<index>

视频链接:15.索引简介&原理(一)_哔哩哔哩_bilibili

说明

        索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

原理

        从根本上说,MongoDB中的索引与其他数据库系统中的索引类似。MongoDB在集合层面上定义了索引,并支持对MongoDB集合中的任何字段或文档的子字段进行索引。

       默认_id已经创建了索引。

操作

视频链接:16.索引的基本操作(二)_哔哩哔哩_bilibili

0、创建索引

 > db.集合名称.createIndex(keys, options)
 > db.集合名称.createIndex({"title":1,"description":-1})

  说明: 语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。

createIndex() 接收可选参数,可选参数列表如下:

ParameterTypeDescription
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
namestring索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
sparseBoolean对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSecondsinteger指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
vindex version索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weightsdocument索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_languagestring对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_overridestring对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

1、查看集合索引

 > db.集合名称.getIndexes()

2、查看集合索引大小

 > db.集合名称.totalIndexSize()

3、删除集合所有索引(不包含_id索引)

 > db.集合名称.dropIndexes()  

4、删除集合指定索引

 > db.集合名称.dropIndex("索引名称")

复合索引

视频链接:17.索引之复合索引(三)_哔哩哔哩_bilibili

说明: 一个索引的值是由多个 key 进行维护的索引的称之为复合索引

 > db.集合名称.createIndex({"title":1,"description":-1})

注意: mongoDB 中复合索引和传统关系型数据库一致都是左前缀匹配原则

聚合<aggregate>

视频链接:18.聚合查询_哔哩哔哩_bilibili

说明

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

使用

 db.test.insertMany([
     {
        title: 'MongoDB Overview', 
        description: 'MongoDB is no sql database',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 100
     },
     {
        title: 'NoSQL Overview', 
        description: 'No sql database is very fast',
        by_user: 'runoob.com',
        url: 'http://www.runoob.com',
        tags: ['mongodb', 'database', 'NoSQL'],
        likes: 10
     },
     {
        title: 'Neo4j Overview', 
        description: 'Neo4j is no sql database',
        by_user: 'Neo4j',
        url: 'http://www.neo4j.com',
        tags: ['neo4j', 'database', 'NoSQL'],
        likes: 750
     }
 ]);

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:

 > db.test.aggregate([{$group : {
                      _id : "$by_user", 
                      num_tutorial : {$sum : 1}
 }}])

注意:此处的_id是分组表示,不是文档的 _id.

常见聚合表达式

表达式描述实例
$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"}}}])

整合应用

视频链接:19.Navicat 连接 MongoDB_哔哩哔哩_bilibili

主要讲解Navicat如何连接MongoDB

附:navicat连接mongoDB不显示数据库,navicat连接mongoDB进行数据管理操作_天天喝可乐的博客-CSDN博客

视频链接:20.整合SpringBoot之环境搭建&集合操作(一)_哔哩哔哩_bilibili

说明: 这里主要以 springboot 应用为基础应用进行整合开发。

Spring Data : Spring 数据框架 JPA 、Redis、Elasticsearch、AMQP、MongoDB

JdbcTemplate

RedisTemplate

ElasticTempalte

AmqpTemplate

MongoTemplate

SpringBoot Spring Data MongoDB

环境搭建

 # 引入依赖
 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
 </dependency>
 # 编写配置
 # mongodb 没有开启任何安全协议
 # mongodb(协议)://121.5.167.13(主机):27017(端口)/baizhi(库名)
 spring.data.mongodb.uri=mongodb://121.5.167.13:27017/baizhi
 ​
 # mongodb 存在密码
 #spring.data.mongodb.host=tx.chenyn.cn
 #spring.data.mongodb.port=27017
 #spring.data.mongodb.database=baizhi
 #spring.data.mongodb.username=root
 #spring.data.mongodb.password=root

集合操作

  • 创建集合

     @Test
     public void testCreateCollection(){
       mongoTemplate.createCollection("users");//参数: 创建集合名称
     }

    注意: 创建的集合已经存在时,再次创建会报错,因此创建前需要判断集合时候已经存在

     /**
      * 创建集合
      */
     @Test
     public void testCreateCollection(){
         // 判断集合是否存在
         boolean isExist = mongoTemplate.collectionExists("products");
         // 不存在时创建集合
         if (!isExist) {
             mongoTemplate.createCollection("products");
         }
     }
  • 删除集合

     /**
      * 删除集合
      */
     @Test
     public void testDropCollection(){
         mongoTemplate.dropCollection("products");
     }

相关注解

视频链接:21.整合SpringBoot之文档的添加(二)_哔哩哔哩_bilibili

Java-->对象-->JSON-->MongoDB

类---文档

  • @Document 对应 类

    • 修饰范围: 用在类上

    • 作用: 用来映射这个类的一个对象为 mongo 中一条文档数据

    • 属性:(value 、collection )用来指定操作的集合名称

  • @Id 对应 要指定为_id的变量名

    • 修饰范围: 用在成员变量、方法上,只能出现一次

    • 作用: 用来将成员变量的值映射为文档的_id 的值

  • @Field 对应 剩余变量名(变量名都按照类中属性名定义时,可以不指定,即同名时可不指定)

    • 修饰范围: 用在成员变量、方法上

    • 作用: 用来将成员变量以及值映射为文档中一个key、value对

    • 属性: ( name,value)用来指定在文档中 key 的名称,默认为成员变量名

  • @Transient 不参与文档转换

    • 修饰范围: 用在成员变量、方法上

    • 作用 : 用来指定改成员变量,不参与文档的序列化

文档操作

视频链接:22.整合SpringBoot之文档的查询(三)_哔哩哔哩_bilibili

视频链接:23.整合SpringBoot之文档的查询(四)_哔哩哔哩_bilibili

  • 查询

    • Criteria

    • 常见查询

       @Test
       public void testQuery(){
         //基于 id 查询
         template.findById("1",User.class);
       ​
         //查询所有
         template.findAll(User.class);
         template.find(new Query(),User.class);
       ​
         //等值查询
         template.find(Query.query(Criteria.where("name").is("编程不良人")), 
                      User.class);
       ​
         // > gt  < lt  >= gte  <= lte
         template.find(Query.query(Criteria.where("age").lt(25)),
                       User.class);
         template.find(Query.query(Criteria.where("age").gt(25)),
                       User.class);
         template.find(Query.query(Criteria.where("age").lte(25)),
                       User.class);
         template.find(Query.query(Criteria.where("age").gte(25)),
                       User.class);
       ​
         //and
         template.find(Query.query(Criteria.where("name").is("编程不良人")
                                   .and("age").is(23)),User.class);
       ​
         //or
         Criteria criteria = new Criteria()
           .orOperator(Criteria.where("name").is("编程不良人_1"),
            Criteria.where("name").is("编程不良人_2"));
         template.find(Query.query(criteria), User.class);
       ​
         //and or
         Criteria criteria1 = new Criteria()
           .and("age").is(23)
           .orOperator(
           Criteria.where("name").is("编程不良人_1"),
           Criteria.where("name").is("编程不良人_2"));
         template.find(Query.query(criteria1), User.class);
       ​
         //sort 排序
         Query query = new Query();
         query.with(Sort.by(Sort.Order.desc("age")));//desc 降序  asc 升序
         template.find(query, User.class);
       ​
       ​
         //skip limit 分页
         Query queryPage = new Query();
         queryPage.with(Sort.by(Sort.Order.desc("age")))//desc 降序  asc 升序
           .skip(0) //起始条数
           .limit(4); //每页显示记录数
         template.find(queryPage, User.class);
       ​
       ​
         //count 总条数
         template.count(new Query(), User.class);
       ​
         //distinct 去重
         //参数 1:查询条件 参数 2: 去重字段  参数 3: 操作集合  参数 4: 返回类型
         template.findDistinct(new Query(), "name", 
                               User.class, String.class);
         
         //使用 json 字符串方式查询 
               Query query = new BasicQuery(
                 "{$or:[{name:'编程不良人'},{name:'徐凤年'}]}", 
                 "{name:0}");
       ​
         template.find(query, User.class);
       }
  • 添加

     @Test
     public void testSaveOrUpdate(){
       User user = new User();
       user.setId("1");
       user.setAge(23);
       user.setName("编程不良人_1");
       user.setBir(new Date());
       User userDB = mongoTemplate.insert(user);//返回保存的对象 insert or save
       System.out.println(userDB);
     }
    • 插入重复数据时:

      • insertDuplicateKeyException提示主键重复;

      • save对已存在的数据进行更新。

    • 批处理操作时:

      • insert可以一次性插入整个数据,效率较高;

      • save需遍历整个数据,一次插入或更新,效率较低。

  • 更新24.整合SpringBoot之文档的更新&删除(五)_哔哩哔哩_bilibili

     @Test
     public void  testUpdate(){
       //1.更新条件
       Query query = Query.query(Criteria.where("age").is(23));
       //2.更新内容
       Update update = new Update();
       update.set("name","编程小陈陈");
     ​
       //单条更新
       mongoTemplate.updateFirst(query, update, User.class);
       //多条更新
       mongoTemplate.updateMulti(query, update, User.class);
       //更新插入
       mongoTemplate.upsert(query,update,User.class);
     ​
       //返回值均为 updateResult
       //System.out.println("匹配条数:" + updateResult.getMatchedCount());
       //System.out.println("修改条数:" + updateResult.getModifiedCount());
       //System.out.println("插入id_:" + updateResult.getUpsertedId());
     }
  • 删除

     @Test
     public void testDelete(){
       //删除所有
       mongoTemplate.remove(new Query(),User.class);
       //条件删除
       mongoTemplate.remove(
         Query.query(Criteria.where("name").is("编程不良人")),
         User.class
       );
     }

项目实操

  • pom.xml依赖

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 ​
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-test</artifactId>
     <scope>test</scope>
 </dependency>
 <!--spring-boot-starter-data-mongodb-->
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-mongodb</artifactId>
 </dependency>
 ​
 <!--lombok-->
 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
 </dependency>
 ​
  • application.properties配置

 # 建立连接
 spring.data.mongodb.uri=mongodb://127.0.0.1:27017/cjn
 ​
  • 实体类User

 package com.study.entity;
 ​
 import lombok.*;
 import lombok.experimental.Accessors;
 import org.springframework.data.annotation.Id;
 import org.springframework.data.mongodb.core.mapping.Document;
 import org.springframework.data.mongodb.core.mapping.Field;
 ​
 import java.util.Date;
 ​
 /**
  * @ClassName User
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2023/3/18 22:21
  * @Version 1.0
  */
 @Data
 @Accessors(chain = true)
 @Document(value = "users")
 public class User {
     @Id
     private Integer id;
 ​
     @Field(value = "username")
     private String name;
 ​
     @Field
     private Double salary;
 ​
     @Field
     private Date birthday;
 }
 ​
  • 测试类

 package com.study.test;
 ​
 import com.mongodb.client.result.DeleteResult;
 import com.mongodb.client.result.UpdateResult;
 import com.study.entity.User;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.BasicQuery;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 ​
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 ​
 /**
  * @ClassName MongodbTest
  * @Description TODO
  * @Author Jiangnan Cui
  * @Date 2023/3/18 21:34
  * @Version 1.0
  */
 @SpringBootTest
 public class MongodbTest {
     @Autowired
     private MongoTemplate mongoTemplate;
 ​
     /**
      * 创建集合
      */
     @Test
     public void testCreateCollection() {
         // 判断集合是否存在
         boolean isExist = mongoTemplate.collectionExists("products");
         // 不存在时创建集合
         if (!isExist) {
             mongoTemplate.createCollection("products");
         }
     }
 ​
     /**
      * 删除集合
      */
     @Test
     public void testDropCollection() {
         mongoTemplate.dropCollection("products");
     }
 ​
     /**
      * 添加单个文档1
      */
     @Test
     public void testSaveDocument() {
         User user = new User();
         user.setId(1)
                 .setName("熊大")
                 .setSalary(800.0)
                 .setBirthday(new Date());
         mongoTemplate.save(user);
     }
 ​
     /**
      * 添加单个文档2
      */
     @Test
     public void testAddDocument() {
         User user = new User();
         user.setId(2)
                 .setName("熊二")
                 .setSalary(500.0)
                 .setBirthday(new Date());
         mongoTemplate.insert(user);
     }
 ​
     /**
      * 批量添加文档
      */
     @Test
     public void testBatchInsertDocument() {
         List<User> userList = new ArrayList<>();
         userList.add(new User().setId(6).setName("猪猪侠").setSalary(1000.0).setBirthday(new Date()));
         userList.add(new User().setId(7).setName("小呆呆").setSalary(600.0).setBirthday(new Date()));
         userList.add(new User().setId(8).setName("波比").setSalary(50.0).setBirthday(new Date()));
 //        mongoTemplate.insert(userList, User.class);
         // 上下两种方式均可,上面指定类名,下面指定集合名
         mongoTemplate.insert(userList, "users");
     }
 ​
     /**
      * 查询操作
      */
     @Test
     public void testFind() {
         // 1.查询所有
         List<User> users = mongoTemplate.findAll(User.class, "users");
         users.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 或
         List<User> userList = mongoTemplate.findAll(User.class);
         userList.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 2.基于id查一个
         User user = mongoTemplate.findById(1, User.class, "users");
         System.out.println(user);
 ​
         System.out.println();
 ​
         // 或
         User user2 = mongoTemplate.findById(1, User.class);
         System.out.println(user2);
 ​
         System.out.println();
 ​
         // 3.条件查询
         // 3.1 查询所有
         List<User> users2 = mongoTemplate.find(
                 new Query(), User.class, "users"
         );
         users2.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 或
         List<User> usersList2 = mongoTemplate.find(
                 new Query(), User.class
         );
         usersList2.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 3.2 等值查询:注意值要写对类型,例如不要将Integer写成String
         List<User> users3 = mongoTemplate.find(
                 new Query(Criteria.where("salary").is(600)), User.class
         );
         users3.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 3.3 不等值查询
         List<User> users1 = mongoTemplate.find(
                 new Query().addCriteria(Criteria.where("salary").gt(800)), User.class
         );
         users1.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 3.4 and查询
         List<User> users4 = mongoTemplate.find(
                 new Query().addCriteria(Criteria.where("salary").gt(800).and("name").is("光头强")), User.class
         );
         users4.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 3.5 or查询
         List<User> users5 = mongoTemplate.find(
                 new Query().addCriteria(
                         new Criteria().orOperator(
                                 Criteria.where("salary").gt(800),
                                 Criteria.where("name").is("小呆呆"))),
                 User.class
         );
         users5.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 3.6 and、or查询连用
         List<User> users6 = mongoTemplate.find(
                 new Query().addCriteria(
                                 new Criteria().orOperator(
                                         Criteria.where("name").in("光头强", "小呆呆")))
                         .addCriteria(Criteria.where("salary").is(600)), User.class
         );
         users6.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 4.排序
         List<User> users7 = mongoTemplate.find(
                 new Query().with(Sort.by(Sort.Order.desc("salary"))), User.class
         );
         users7.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 5.排序后分页
         List<User> users8 = mongoTemplate.find(
                 new Query().with(Sort.by(Sort.Order.asc("salary")))
                         .skip(0)
                         .limit(2), User.class
         );
         users8.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 6.查询总条数
         long count = mongoTemplate.count(new Query(), User.class);
         System.out.println("count = " + count);
 ​
         System.out.println();
 ​
         // 7.去重
         List<Double> salaryList = mongoTemplate.findDistinct(new Query(), "salary", User.class, Double.class);
         salaryList.forEach(System.out::println);
 ​
         System.out.println();
 ​
         // 8.使用json字符串方式查询
         Query query = new BasicQuery("{$or: [{name:'小呆呆'},{name:'光头强'}]}", "{birthday:0}");
         List<User> users9 = mongoTemplate.find(
                 query, User.class
         );
         users9.forEach(System.out::println);
     }
 ​
     /**
      * 更新文档
      */
     @Test
     public void testUpdateDocument() {
         Update update = new Update();
         update.set("salary", 2500);
         // 更新一条
         mongoTemplate.updateFirst(
                 Query.query(Criteria.where("salary").is(1000)),
                 update,
                 User.class);
 ​
         update.set("salary", 1500);
         // 更新多条
         mongoTemplate.updateMulti(
                 Query.query(Criteria.where("salary").lt(200)),
                 update,
                 User.class
         );
 ​
         // 插入更新
         update.setOnInsert("id", 10);
         update.set("name", "我是之前没有的");
         // 更新多条
         UpdateResult updateResult = mongoTemplate.upsert(
                 Query.query(Criteria.where("salary").gt(30000)),
                 update,
                 User.class
         );
         System.out.println("updateResult.getMatchedCount() = " + updateResult.getMatchedCount());
         System.out.println("updateResult.getModifiedCount() = " + updateResult.getModifiedCount());
         System.out.println("updateResult.getUpsertedId() = " + updateResult.getUpsertedId());
     }
 ​
     /**
      * 文档删除
      */
     @Test
     public void testRemoveDocument() {
         DeleteResult deleteResult = mongoTemplate.remove(Query.query(Criteria.where("id").is(9)), User.class);
         System.out.println("deleteResult.getDeletedCount() = " + deleteResult.getDeletedCount());
     }
 }
 ​

副本集<Replica Set>

视频链接:25.副本集简介(一)_哔哩哔哩_bilibili

说明

Replication — MongoDB Manual

       MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用。注意:这种方式并不能解决主节点的单点访问压力问题。

Automatic Failover

       自动故障转移机制: 当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为 10 秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。

搭建副本集

视频链接:26.副本集搭建(二)_哔哩哔哩_bilibili

  • 创建数据目录

     # 在安装目录中创建
     - mkdir -p ../repl/data1
     - mkdir -p ../repl/data2
     - mkdir -p ../repl/data3
  • 搭建副本集:单独操作 当前机器的ip地址

     $ mongod --port 27017  --dbpath ../repl/data1 --bind_ip 0.0.0.0 --replSet  myreplace/[121.5.167.13:27018,121.5.167.13:27019]
     ​
     $ mongod --port 27018  --dbpath ../repl/data2 --bind_ip 0.0.0.0 --replSet  myreplace/[121.5.167.13:27019,121.5.167.13:27017]
     ​
     $ mongod --port 27019  --dbpath ../repl/data3 --bind_ip 0.0.0.0 --replSet  myreplace/[121.5.167.13:27017,121.5.167.13:27018]

注意: --replSet 副本集 myreplace 副本集名称/集群中其他节点的主机和端口

  • 配置副本集,连接任意节点

    • use admin

    • 初始化副本集

       > var config = { 
               _id:"myreplace", 
               members:[
               {_id:0,host:"121.5.167.13:27017"},
               {_id:1,host:"121.5.167.13:27018"},
               {_id:2,host:"121.5.167.13:27019"}]
       }
       > rs.initiate(config);//初始化配置 
    • 设置客户端临时可以访问

       > rs.slaveOk();  旧的
       > rs.secondaryOk();  新的

注意:当MongoDB副本集架构只剩一个节点时,整个节点是不可用的。单主不可写。

视频链接27.客户端操作副本集以及 Bug 说明_哔哩哔哩_bilibili

MongoDB与Navicat(直连主节点就行,连接多个节点时会提示超时)、IDEA连接(修改配置)

可参考:Mongodb学习笔记(编程不良人,基于5.0.5)_编程不良人mongodb笔记_chihiro_db的博客-CSDN博客

分片集群<Sharding Cluster>

视频链接:28.分片集群(一)_哔哩哔哩_bilibili

说明

官网Sharding — MongoDB Manual

   分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时也用分区(partitioning)来表示这个概念,将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。

       分片目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用运行。

       MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。 

       MongoDB分片的基本思想就是将集合拆分成多个块,这些快分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。

架构

  • Shard: 用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障

  • Config Server:mongod实例,存储了整个 ClusterMetadata。

  • Query Routers: 前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。

  • Shard Key: 片键,设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key),片键的选取很重要,片键的选取决定了数据散列是否均匀。

搭建

视频链接:29.分片搭建(二)_哔哩哔哩_bilibili

视频链接:30.集群搭建(三)_哔哩哔哩_bilibili

 # 1.集群规划
 - Shard Server 1:27017
 - Shard Repl   1:27018
 ​
 - Shard Server 2:27019
 - Shard Repl   2:27020
 ​
 - Shard Server 3:27021
 - Shard Repl   3:27022
 ​
 - Config Server :27023
 - Config Server :27024
 - Config Server :27025
 ​
 - Route Process :27026
 ​
 # 2.进入安装的 bin 目录创建数据目录
 - mkdir -p ../cluster/shard/s0
 - mkdir -p ../cluster/shard/s0-repl
 ​
 - mkdir -p ../cluster/shard/s1
 - mkdir -p ../cluster/shard/s1-repl
 ​
 - mkdir -p ../cluster/shard/s2
 - mkdir -p ../cluster/shard/s2-repl
 ​
 - mkdir -p ../cluster/shard/config1
 - mkdir -p ../cluster/shard/config2
 - mkdir -p ../cluster/shard/config3
 ​
 # 3.启动4个 shard服务
 ​
 # 启动 s0、r0
 > ./mongod --port 27017 --dbpath ../cluster/shard/s0 --bind_ip 0.0.0.0 --shardsvr --replSet r0/121.5.167.13:27018
 > ./mongod --port 27018 --dbpath ../cluster/shard/s0-repl --bind_ip 0.0.0.0 --shardsvr --replSet r0/121.5.167.13:27017
 -- 1.登录任意节点
 -- 2. use admin
 -- 3. 执行
         config = { _id:"r0", members:[
       {_id:0,host:"121.5.167.13:27017"},
       {_id:1,host:"121.5.167.13:27018"},
         ]
     }
         rs.initiate(config);//初始化
 ​
 # 启动 s1、r1
 > ./mongod --port 27019 --dbpath ../cluster/shard/s1 --bind_ip 0.0.0.0 --shardsvr  --replSet r1/121.5.167.13:27020
 > ./mongod --port 27020 --dbpath ../cluster/shard/s1-repl --bind_ip 0.0.0.0 --shardsvr --replSet r1/121.5.167.13:27019
 -- 1.登录任意节点
 -- 2. use admin
 -- 3. 执行
         config = { _id:"r1", members:[
       {_id:0,host:"121.5.167.13:27019"},
       {_id:1,host:"121.5.167.13:27020"},
         ]
     }
         rs.initiate(config);//初始化
 ​
 # 启动 s2、r2
 > ./mongod --port 27021 --dbpath ../cluster/shard/s2 --bind_ip 0.0.0.0 --shardsvr --replSet r2/121.5.167.13:27022
 > ./mongod --port 27022 --dbpath ../cluster/shard/s2-repl --bind_ip 0.0.0.0 --shardsvr --replSet r2/121.5.167.13:27021
 -- 1.登录任意节点
 -- 2. use admin
 -- 3. 执行
         config = { _id:"r2", members:[
       {_id:0,host:"121.5.167.13:27021"},
       {_id:1,host:"121.5.167.13:27022"},
         ]
     }
         rs.initiate(config);//初始化
 ​
 # 4.启动3个config服务
 ​
 > ./mongod --port 27023 --dbpath ../cluster/shard/config1 --bind_ip 0.0.0.0 --replSet  config/[121.5.167.13:27024,121.5.167.13:27025] --configsvr
 ​
 > ./mongod --port 27024 --dbpath ../cluster/shard/config2 --bind_ip 0.0.0.0 --replSet  config/[121.5.167.13:27023,121.5.167.13:27025] --configsvr
 ​
 > ./mongod --port 27025 --dbpath ../cluster/shard/config3 --bind_ip 0.0.0.0 --replSet  config/[121.5.167.13:27023,121.5.167.13:27024] --configsvr
 ​
 # 5.初始化 config server 副本集
 - `登录任意节点 congfig server`
 > 1.use admin 
 > 2.在admin中执行
   config = { 
       _id:"config", 
       configsvr: true,
       members:[
           {_id:0,host:"121.5.167.13:27023"},
           {_id:1,host:"121.5.167.13:27024"},
           {_id:2,host:"121.5.167.13:27025"}
         ]
   }
 > 3.rs.initiate(config); //初始化副本集配置 
 ​
 # 6.启动 mongos 路由服务
 ​
 > ./mongos --port 27026 --configdb config/121.5.167.13:27023,121.5.167.13:27024,121.5.167.13:27025 --bind_ip 0.0.0.0 
 ​
 # 7.登录 mongos 服务
 > 1.登录 mongo --port 27026
 > 2.use admin
 > 3.添加分片信息
     db.runCommand({ addshard:"r0/121.5.167.13:27017,121.5.167.13:27018",
     "allowLocal":true });
     db.runCommand({ addshard:"r1/121.5.167.13:27019,121.5.167.13:27020",
     "allowLocal":true });
     db.runCommand({ addshard:"r2/121.5.167.13:27021,121.5.167.13:27022",
     "allowLocal":true });
 > 4.指定分片的数据库
     db.runCommand({ enablesharding:"baizhi" });
 ​
 > 5.设置库的片键信息
     db.runCommand({ shardcollection: "baizhi.users", key: { _id:1}});
     db.runCommand({ shardcollection: "baizhi.emps", key: { _id: "hashed"}})

完结 

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值