MongoDB


MongoDB

简介

以json为数据模型的文档型数据库
应用型数据库存储海量数据
动态建模,没有特定字段格式
支持副本机制,分片机制,为分布式而生

安装

  • win
    Windows下载:https://www.mongodb.com/try/download/community
    设置数据库文件存储路径和日志存储路径
    不要安装MongoDB-Compass(图形化界面)
    配置环境变量(安装目录下bin目录)
    为MongoDB添加一个数据库文件夹db,新建一个文件夹安装路径\data\db,这个文件夹会储存数据库的数据

  • linux

    下载:https://www.mongodb.com/try/download/community
    tar -zxvf mongodb-7.0.32.tgz
    # 数据目录
    sudo mkdir -p /var/lib/mongodb
    # 日志目录
    sudo mkdir -p /var/log/mongodb
    # 配置文件目录
    sudo mkdir -p /etc/mongodb
    vi /etc/mongodb/mongod.conf
    # mongod.conf
    # 日志
    systemLog:
      destination: file
      path: /var/log/mongodb/mongod.log
      logAppend: true
    
    # 数据存储
    storage:
      dbPath: /var/lib/mongodb
      wiredTiger:
        engineConfig:
          cacheSizeGB: 2
    
    # 网络
    net:
      port: 27017
      bindIp: 127.0.0.1
    
    # 进程控制
    processManagement:
      fork: false # 系统服务需要配置false
    
    # 安全
    security:
      authorization: disabled
    # 系统服务
    # vi /etc/systemd/system/mongod.service
    [Unit]
    Description=MongoDB Database Server
    Documentation=https://docs.mongodb.org/manual
    After=network.target
    
    [Service]
    User=root
    Group=root
    Environment="OPTIONS=-f /etc/mongodb/mongod.conf"
    ExecStart=/usr/local/mongodb-7/bin/mongod $OPTIONS
    ExecStop=/usr/local/mongodb-7/bin/mongod --shutdown --dbpath /var/lib/mongodb
    PIDFile=/var/run/mongodb/mongod.pid
    Restart=on-failure
    LimitNOFILE=64000
    
    [Install]
    WantedBy=multi-user.target
    systemctl daemon-reload
    systemctl start mongod
    systemctl enable mongod
    systemctl status mongod
    下载mongosh
    https://www.mongodb.com/try/download/shell
    tar -zxvf mongosh-2.8.tgz
    ./mongosh
    进入创建用户密码,然后security.authorization 改成 enabled

MongoDB 后台管理 Shell

执行安装目录下bin目录下mongo.exe文件,MongoDB Shell是MongoDB自带的交互式Javascript shell,用来对MongoDB进行操作和管理的交互式环境。
相关命令

db:  # 查看当前操作数据库
show databases
use demo # 使用/创建
db.users.insertOne({"name":"zhangsan",age:18}) # 插入数据到集合users
db.users.find()  # 查看
# id是客户端生成的
ObjectId("64704ebce4ed76702416307f").getTimestamp()
db.dropDatabase()  #删除数据库,先切换到指定数据库
db.collection.drop()  #删除集合
db.users.insertMany([{doc}, {doc}],
{
	writeConcern: doc,
	ordered: true/false #有序(一旦失败,后面的也不插入了),无序
})
majority:写操作需要被复制到多大节点数才成功
# 精准查询
db.users.find({name: "test"})
db.users.find({name: "test", age: 11})
db.users.find({name: "test"}, {_id:0, age:1}) # 只返回age字段
db.users.find({$and:[{name: "test"}, {age: 11}]})
db.users.find({$or:[{name: "test"}, {age: 11}]})
db.users.find({age:{$gt:11}})
$ne不等于 $gte大于等于 $lt小于 $lte小于等于
db.users.find({age:{$in:[11,12]}})
$in $nin
db.users.count()
db.users.find().skip(1).limit(2)
db.users.find().sort({age: 1}) # -1逆序
db.movies.insertMany([{name:"test", tag:["动作","热血"]}])
db.movies.find({}, {tag:{$slice:1}}) #slice
db.users.updateOne({name:"test"}, {$set:{flag: 1}}) #有这个字段就修改,没有就追加,One只会改一个匹配值
db.users.updateMany({name:"test"}, {$unset:{flag: 1}}) #删除字段

db.createCollection(name, options)
options: (capped 布尔 是否创建固定大小集合 | size 数值 最大大小,字节 | max 数值 文档的最大数量)
# 创建固定集合 mycol,整个集合空间大小 6142800 B, 文档最大个数为 10000 个。
db.createCollection("mycol", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )
db.col.save(document)   # 不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据
# 更新
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 :可选,抛出异常的级别。

# 更新标题(title),如果修改多条相同的文档需要设置 multi 参数为 true
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
# 删除文档(前面是条件,true代表只删除一条默认为false,全删除)
db.col.remove({'title':'MongoDB 教程'}, true)
# 删除所有
db.col.remove({})
db.col.find().pretty()  # 以格式化的方式来显示所有文档
# 条件语句查询
db.col.find({"by":"test"}).pretty()  # where by = 'test'
db.col.find({"likes":{$lt:50}}).pretty()  # where likes < 50
db.col.find({"likes":{$lte:50}}).pretty()  # where like <= 50
db.col.find({"likes":{$gt:50}}).pretty()  # where likes > 50
db.col.find({"likes":{$ne:50}}).pretty()  # where likes != 50
# AND,OR联合
db.col.find({"likes": {$gt:50}, $or: [{"by": "教程"},{"title": "MongoDB"}]}).pretty()
# 获取 "col" 集合中 title 为 String 的数据
db.col.find({"title" : {$type : 'string'}})
db.col.createIndex({"title":1,"description":-1})  # 建立索引,1升序,-1降序,这是复合索引
db.col.createIndex({ email: 1 }, { unique: true }) # 唯一索引
db.col.createIndex({ field: 1 }, { name: "idx_field" }) # 指定索引名称
db.col.dropIndex("idx_field")       // 按名称删除
# 使用aggregate()计算  类似:select by_user, count(*) from mycol group by by_user
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])  

权限

添加用户

创建一个用户名root,密码root的管理员

use admin
db.createUser({user:"admin",pwd:"xxx",roles:[{role:"root",db:"admin"}]})

超级用户一定是属于admin数据库的

开启远程链接

修改mongodb.cfg

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1,0.0.0.0

开启密码登录

修改mongodb.cfg

# network interfaces
security:
 authorization: enabled

主从

复制集:实现服务高可用,类似Redis哨兵,复制集最多50节点,投票最多7
数据写入主节点时将数据复制到副本
主节点发生故障自动选举一个新的主节点

搭建

cd /data/
mkdir db1 mkdir db2 mkdir db3
// 创建日志文件
touch db1/mongod.log touch db2/mongod.log touch db3/mongod.log
// 创建配置文件
touch db1/mongod.conf touch db1/mongod.conf touch db1/mongod.conf
// conf内容(配置三个,改path,dbpath,port)
systemLog:
  destination: file
  path: /data/db1/mongod.log
  logAppend: true
storage:
  dbPath: /data/db1
net:
  bindIp: 0.0.0.0
  port: 28017
replication:
  replSetName: rs0
processManagement:
  fork: true
  • 启动
    mongod -f /data/db1/mongod.conf
    mongod -f /data/db2/mongod.conf
    mongod -f /data/db3/mongod.conf
    // 连接任一复制集
    mongo --port 28017
    // 配置
    var config={_id:"rs0",members:[{_id:0,host:"localhost:28017"},{_id:1,host:"localhost:28018"},{_id:2,host:"localhost:28019"}]}
    rs.initiate(config)
  • 从节点读
    默认从节点不能读,需在从节点配置
    rs.secondaryOk()
    只有主节点能写

分片集群

将数据水平拆分到不同服务器,并发量突破单机性能瓶颈
路由节点,数据节点,配置节点

路由节点:提供集群单一入口,转发应用端请求,选择合适数据节点进行读写
配置节点:存储集群相关信息
数据节点:以复制集为单位,横向扩展,分片之间数据不重复,所有数据在一起才可以完整工作

Java连接

   <dependency>
       <groupId>org.mongodb</groupId>
       <artifactId>mongodb-driver-sync</artifactId>
       <version>4.1.1</version>
   </dependency>
	
public static void main(String[] args) {
       MongoClient mongoClient = MongoClients.create("mongodb://192.168.31.8:28017");
       // 获取数据库
       MongoDatabase mongoDatabase = mongoClient.getDatabase("zwq");
       // 获取集合
       MongoCollection<Document> users = mongoDatabase.getCollection("users");
       Document doc = new Document("name", "bob").append("age", 22);
       users.insertOne(doc);

       Bson eq = eq("name", "bob");
       FindIterable<Document> find = users.find(eq);
       Document findUser = find.first();
       System.out.println(findUser);
   }

springboot

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
    <optional>true</optional>
</dependency>
spring:
  data:
    mongodb:
      # 集群配置mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
      # uri: mongodb://192.168.204.81:27017,192.168.204.82:27017,192.168.204.83:27017/testdb?maxPoolSize=512
      uri: mongodb://192.168.31.8:28017/zwq?maxPoolSize=512
      # authentication-database: admin # 登录认证的逻辑库名
      # username: admin #用户名
      # password: abc123456 #密码
  • 实体
    @Data
    @Document(collection = "users")
    public class User {
        @Id
        private String id;
        private String name;
        private Integer age;
    }
  • service
    public interface UserService extends MongoRepository<User, String> {
    }
  • controller
    @RestController
    public class UserController {
    
        @Autowired
        UserService userService;
    
        @RequestMapping("/users")
        public void users() {
            List<User> list = userService.findAll();
            list.stream().forEach((item) -> {
                System.out.println(item.toString());
            });
        }
    
    }

python集成

# pip install pymongo

from pymongo import MongoClient

# 底层默认维护一个100大小的连接池,使用的时候动态分配和释放,每次调用这个client即可,程序结束的时候再关闭client
client = MongoClient('mongodb://zwq:zwq123465@localhost:27017/')
db = client['test']
collection = db['order']


def create_collection(database_name, collection_name):
    database_c = client[database_name]
    collection_c = database_c.create_collection(collection_name)
    return collection_c


def rename_collection(database_name, collection_name, rename):
    database_c = client[database_name]
    database_c[collection_name].rename(rename)


def del_collection(database_name, collection_name):
    database_c = client[database_name]
    database_c[collection_name].drop()


doc = {'name': '张三', 'age': 28, 'city': '北京'}
docs = [
    {'name': '李四', 'age': 32, 'city': '上海'},
    {'name': '王五', 'age': 25, 'city': '广州'}
]

# 插入一条
result = collection.insert_one(doc)

# 插入多条
result = collection.insert_many(docs)

# 查询一条
one = collection.find_one({'name': '张三'})

# 查询多条(返回游标,转成列表)
cursor = collection.find({'age': {'$gte': 25}})

# 带条件、排序、限制
cursor = collection.find({'city': '北京'}).sort('age', -1).limit(2)

# 更新一条(将张三的年龄加1)
collection.update_one({'name': '张三'}, {'$inc': {'age': 1}})

# 更新多条(age<30)
collection.update_many({'age': {'$lt': 30}}, {'$set': {'city': '深圳'}})

# 删除一条
collection.delete_one({'name': '王五'})

# 删除多条(age>40)
collection.delete_many({'age': {'$gt': 40}})

# 删除所有
collection.delete_many({})

# count
count = collection.count_documents({'city': '北京'})

# ========== 关闭连接 ==========
client.close()

  目录