mongodb数据库使用分享

Posted 香菜+

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb数据库使用分享相关的知识,希望对你有一定的参考价值。

基本概念

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

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库

NoSQL

非关系型数据库的一系列统称,常见的比如redis,mongodb,neo4j;mongodb 以文档的形式存储数据,数据表现形式和JSON类似,MongoDB里面叫BSON,BSON会支持一些JSON不支持的数据格式,如Date,BinData

SQL术语/概念

MongoDB术语/概念

解释/说明

database

database

数据库

table

collection

数据库表/集合

row

document

数据记录行/文档

column

field

数据字段/域

index

index

索引

table joins

lookup

表连接

primary key

primary key

主键,MongoDB自动将_id字段设置为主键

应用场景

如果项目的数据模式是固定的,而且不需要频繁变更,推荐使用 mysql,因此项目维护容易,而且确保了数据的完整性和可靠性。

另一方面,如果项目中的数据持续增加,而且数据模式不固定,MongoDB 是最合适的选择。由于它属于非关系数据库,数据可以自由使用,不需要定义统一的数据结构,所以对数据进行更新和查询也很方便。MongoDB 通常用于需要对内容进行管理、处理物联网相关业务、进行实时分析等功能的项目中。

技术解析

系统架构

主从模式(Master-Slave)

热备,读写分离,oplog同步数据;数据一致性问题;主节点宕机需要手动把slave节点指定为master节点,无法自愈(不推荐)

副本集模式(Replica Set)

和redis的哨兵模式类似

"脑裂"问题

分片模式(sharding)

可以简单地理解为是副本集模式的集群模式,并且加了一层代理层和配置层

代理层:访问数据时路由到具体的副本集

配置层:帮忙做负载均衡的

事务

4.0开始支持事务(副本集模式)

4.2及以上支持(分片模式的事务)

建议做合理的数据表格设计,尽量做单文档操作

数据存储引擎

WiredTiger:数据存放在磁盘上

In-Memory:数据存放在内存中(mongo进程杀掉之后就没数据量,需要通过oplog日志来恢复)

一般来讲主节点一定要WiredTiger,从节点可以用In-Memory提高效率

索引

b树(索引+数据)

非关系型数据库mongodb 设计表格时区别于关系型数据库的设计;关系型数据设计需要遵循3范式,多表查询遍历多,需要读取更多的索引;非关系型数据库 比较适合单一查询,不涉及遍历操作

基本语法

常用指令

xshell 登录172.26.1.247

cd /home
sh enter_container.sh mongo
mongosh

enter_container.sh

#!/bin/bash

echo "container name: $1"

containerId=$(docker ps |grep "$1" | awk 'print $1')

echo "get containerId: $containerId"

docker exec -it "$containerId" /bin/sh
#查看已有数据库
show dbs
#创建使用数据库
use ccp_monitor
#mongo中不需要事先建立表格,插入数据时自动生成
db.userinfo.insert("name":"lsj","age":18)

#但需要自己创建索引,注意要设置background=true 不然会锁表
#创建普通索引
db.userinfo.createIndex("name":1,background:true)
#创建唯一索引
db.userinfo.createIndex("userId":1,background:true,unique:true)
#创建联合索引
db.userinfo.createIndex("name":1,"sex":1,background:true)

增删改查

添加记录

#添加记录
db.tablename.insert(json数据)
#example
db.userinfo.insert("name":"lsj","age":18)

修改记录

#修改记录
db.tablename.update(条件,操作)
#example
db.userinfo.update("name":"cd","sex":1,$set:"age":99)
#插入或更新 
db.userinfo.update("name":"cjf","sex":1,$set:"age":99,"upsert":true)

查询记录

#查询记录
db.tablename.find(条件,返回字段(可选))
#example
#查询user表的所有数据
db.userinfo.find();
#多个检索条件封装成json
db.userinfo.find("name":'cd',"sex":1)
db.userinfo.find("name":'cd',"sex":1,"name":1)

删除记录

#删除记录
db.tablename.remove(条件(可选))
#example
db.userinfo.remove("name":'lsj')

内嵌函数

db.userinfo.find("$where":function()return this.age>40;)

db.userinfo.find("$where":function()return this.age>40&&this.sex==1;)

查询内嵌文档中满足条件的记录

#查询child年龄小于等于5的记录(全部)
db.userinfo.find("child.age":$lte:5)
[
  
    _id: ObjectId("632bd90a29dd2c5a24dbf033"),
    name: 'cjf',
    sex: 1,
    age: 99,
    child: [  name: 'a', age: 10 ,  name: 'b', age: 5  ]
  
]

#查询child年龄小于等于5的记录(符合条件的child)
db.userinfo.find("child.age":$lte:5,"child.$":1)

[
  
    _id: ObjectId("632bd90a29dd2c5a24dbf033"),
    child: [  name: 'b', age: 5  ]
  
]

原子指令操作

应用场景,需要修改某个实体下的某个属性;这个属性可能是一个基本数据类型,也可能是内嵌文档

为了解决这类并发问题,mongo提供了一系列操作符来简化操作

$inc:inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作
$set:用来指定一个键并更新键值,若键不存在并创建;对于内嵌文档在使用$set更新时,使用"."连接的方式
$unset:删除键
$push:数组修改器,向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据
添加时键存在,要求键值类型必须是数组;键不存在,则创建数组类型的键
$pull:从数组field内删除一个等于value值
$addToSet:增加一个值到数组内,而且只有当这个值不在数组内才增加
$pop:删除数组尾部元素(参数1) 删除数组头部元素(参数-1)

表连接查询(基本不用)

db.gameapp.aggregate([
	 
	$match: name: 'qysg10001' 
	,
	$lookup: 
	 	from: 'hosts',
	 	localField: 'host_id',
	 	foreignField: '_id',
	 	as: 'host_info'
	
	,
	$unwind: 
		path: '$host_info',
		preserveNullAndEmptyArrays: true,
		
	,
	$project: 
		_id: 0,
		'host_info.host': 1,
		'host_info.private_ip': 1,
		'host_info.status': 1,		
	

])

图形化界面工具

robo 3t

MongoDB Compass(官方提供的,建议使用)

两个软件都支持页面编辑和指令编辑,都有代码提示

主要演示一下robo 3t的使用,具体看演示

配置连接信息

查看数据

会自动生成一个查询模板

添加/编辑/删除数据

右键

语言集成

java

springboot集成了mongodb驱动,客户端,只需要在pom文件中导入jar包,配置连接信息,利用spring的自动装配原理,管理连接

python

pymongo

from pymongo import MongoClient

if __name__ == '__main__':
    client = MongoClient(host='172.26.1.247', port=27017)

    userinfo = client['ccp_monitor']['userinfo']

    result = userinfo.find_one("name": 'lsj')
    
    print(result)

更多使用方法:API Documentation — PyMongo 4.2.0 documentation

经验分享

1.建索引

本身mongo就是基于b树做索引的,检索的时候索引和数据都会读到,没有索引会导致全表扫描,响应慢

2.创建索引,注意要设置background=true 不然会锁表(生产环境很危险!)

3.原子操作尽量使用数据库自带的

4.尽量使用单表操作,避免外联查询

5.避免使用数据库的唯一id做检索条件

知识拓展

GeoJson

如果不想用postgis,mongodb的GeoJson是最佳选择

以上是关于mongodb数据库使用分享的主要内容,如果未能解决你的问题,请参考以下文章

mongodb数据库使用分享

mongoDB数据库原生配置

MongoDB优化心得分享

前端技术分享:什么是MongoDB数据库?

万亿级数据库MongoDB集群性能数十倍提升及机房多活容灾实践

MySQL 到 MongoDB 实时数据同步实操分享