MongoDB
NoSQL
Not only SQL 性能高,不使用 SQL意味着没有结构化存储要求,没有约束之后架构更加灵活
- 列存储,Hbase
- 键值存储,redis
- 图像存储 Neo4j
- 文档存储,MongoDB
MongoDB体系结构
存储在集合中的数据都是BSON格式,BSON格式是一种类似JSON的二进制存储格式
MongoDB 和 RDBMS(关系型数据库) 对比
- Collection 对应 table 表
- Document 对应 row 行
- Field 对应 column 列
- embedded Document 嵌套文档 对应 join(主外键关联)
MongoDB基本操作
# 查看数据库
show dbs
# 切换数据库
use 数据库名
# 删除当前数据库
db.dropDatabase();
# 创建集合
db.createCollection("order")
show collections
# 删除集合
db.集合.drop();
集合增删改查
查询
use lagou;
db.createCollection("order")
db.oder.insert({name:"joe",birth:new ISODate("2020-01-01)})
# 批量插入
db.oder.insert([{name:"joe",birth:new ISODate("2020-01-01)},
{name:"lee",birth:new ISODate("2021-02-02)}
])
_id ObjectId类型,12字节 BSON类型数据。
- 前4个字节表示时间戳
- 接下来3个字节 机器码
- 紧接着2个字节 进程id
- 最后3个字节 随机数
查询
db.order.find({salary:{$gt:1800}})
db.order.find({salary:{$gte:1800}})
db.order.find({salary:{$lt:1800}})
// 逻辑条件 and
db.order.find({salary:{$lt:1800},city:'beijing'})
// or
db.order.find({$or:[{{salary:1800},{city:'beijing'}]})
// not
db.order.find({salary:{$not:{$eq:1800}}})
// 1 升序,-1 降序
db.order.find({salary:1000}).sort({salary:1})
db.order.find({salary:1000}).sort({salary:1})
.skip(1).limit(2)
更新 删除
// 更新salary 2000到2300,只更新一条,不存在时不插入
db.order.update({salary:2000},{$set:{salary:2300}},
{multi:false,upsert: false})
// 删除joe Document 的salary字段
db.order.update({name:"joe"},{$unset:{salary:2300}},
{multi:false,upsert: false})
// 删除
db.order.remove({name:"joe"})
聚合
// 按照 city分组,city 出现的次数
db.order.aggregate([{$group:{_id:"$city",city_count:{$sum:1}}}])
// 按照 city分组,salary 平均值
db.order.aggregate([{$group:{_id:"$city",avg_salary:{$avg:"$salary"}}}])
// 管道 match相当于 having,对分组后的数据过滤
db.order.aggregate([{$group:{_id:"$city",avg_salary:{$avg:"$salary"}}},{$match:{avg_salary:{$gt:2000}}}])
// MapReduce, Document转为 key-value结构,对city分组salary求平均
db.order.mapReduce(function(){emit(this.city,this.salary)},
function(key,value){return Array.avg(value)},
{out:"avgSalary"})
索引
索引分类
- 过期索引
- 复合索引
- 多键索引,针对数组字段创建的索引
- 地理空间索引
- 全文索引
// 全文索引
db.order.createIndex({description:"text"})
db.order.find({"$text":{"$search":"two"}})
- 哈希索引
db.order.createIndex({"age":"hashed"})
执行计划分析
executionStats返回逐层分析
- executionTimeMillis ,语句的执⾏时间
- executionStages.executionTimeMillisEstimate,检索document获得数据的时间。
- executionStages.inputStage.executionTimeMillisEstimate,查询扫描⽂档 index所⽤时间
stage类型
- COLLSCAN:全表扫描
- IXSCAN:索引扫描
- FETCH:根据索引去检索指定document
- SHARD_MERGE:将各个分⽚返回数据
- PROJECTION:限定返回字段时候stage的返回
- IDHACK:针对_id进⾏查询
索引原理
B-树,所有节点都有Data域,只要找到指定索引就可以访问数据
MongoDB 数据模型
- 内嵌,把相关联的数据保存在同一个文档结构中
- 引用
复制集
复制集是由⼀组拥有相同数据集的mongod实例做组成的集群。
复制集是⼀个集群,它是2台及2台以上的服务器组成,以及复制集成员包括Primary主节点,secondary从节点 和投票节点。
分片集群搭建
use admin;
var cfg = {
"_id": "configsvr",
"members": [
{ "_id": 1, "host": "192.168.184.3:17011" },
{ "_id": 2, "host": "192.168.184.3:17013" },
{ "_id": 3, "host": "192.168.184.3:17015" }]
};
rs.initiate(cfg)
// shard1
var cfg = {
"_id": "shard1",
"protocolVersion": 1,
"members": [
{ "_id": 1, "host": "192.168.184.5:37011", "priority": 10 },
{ "_id": 2, "host": "192.168.184.5:37013" },
{ "_id": 3, "host": "192.168.184.5:37015" },
{ "_id": 4, "host": "192.168.184.5:37017", "arbiterOnly": true }
]
};
rs.initiate(cfg)
rs.reconfig(cfg)
rs.status()
// shard2
var cfg = {
"_id": "shard2",
"protocolVersion": 1,
"members": [
{ "_id": 1, "host": "192.168.184.4:47011", "priority": 10 },
{ "_id": 2, "host": "192.168.184.4:47013" },
{ "_id": 3, "host": "192.168.184.4:47015" },
{ "_id": 4, "host": "192.168.184.4:47017", "arbiterOnly": true }
]
};
rs.initiate(cfg)
rs.reconfig(cfg)
rs.status()
// shard3
var cfg = {
"_id": "shard3",
"protocolVersion": 1,
"members": [
{ "_id": 1, "host": "192.168.184.8:57011", "priority": 10 },
{ "_id": 2, "host": "192.168.184.8:57013" },
{ "_id": 3, "host": "192.168.184.8:57015" },
{ "_id": 4, "host": "192.168.184.8:57017", "arbiterOnly": true }
]
};
rs.initiate(cfg)
rs.reconfig(cfg)
rs.status()
// shard4
var cfg = {
"_id": "shard4",
"protocolVersion": 1,
"members": [
{ "_id": 1, "host": "192.168.184.9:58011", "priority": 10 },
{ "_id": 2, "host": "192.168.184.9:58013" },
{ "_id": 3, "host": "192.168.184.9:58015" },
{ "_id": 4, "host": "192.168.184.9:58017", "arbiterOnly": true }
]
};
rs.initiate(cfg)
rs.reconfig(cfg)
rs.status()
// config
use admin
var cfg = {
"_id": "configsvr",
"members": [
{ "_id": 1, "host": "192.168.184.3:17011" },
{ "_id": 2, "host": "192.168.184.3:17013" },
{ "_id": 3, "host": "192.168.184.3:17015" }]
};
rs.initiate(cfg)
// 添加分片节点
sh.status()
sh.addShard("shard1/192.168.184.5:37011,192.168.184.5:37013,192.168.184.5:37015,192.168.184.5:37017");
sh.addShard("shard2/192.168.184.4:47011,192.168.184.4:47013,192.168.184.4:47015,192.168.184.4:47017");
sh.addShard("shard3/192.168.184.8:57011,192.168.184.8:57013,192.168.184.8:57015,192.168.184.8:57017");
sh.addShard("shard4/192.168.184.9:58011,192.168.184.9:58013,192.168.184.9:58015,192.168.184.9:58017");
sh.enableSharding("lagou_resume")
sh.shardCollection("lagou_resume.lagou_resume_datas", { "name": "hashed" })
// 认证
db.createUser(
{
user: "lagou_gx",
pwd: "abc321",
roles: [{ role: "readWrite", db: "lg_resume" }]
}
)
auth = true
keyFile = /home/scott / Mongodb / config / testKeyFile.file
分片
分片集群
- 路由节点,请求通过路由节点协调
- 配置节点
- 分片节点
Neo4j
NoSql 图形数据库,图数据结构的形式来存储和查询书籍的数据库
Neo4j基础
Neo4j 是开源的无Schema 基于java开发的图形数据库,结构化数据存储在图中。
CQL
Cypher查询语言
-- 创建标签 Person,节点person
create(person:Person)
-- 创建person带有属性
create(person:Person {cid:1,name:"joe"})
-- match
match(p:Person) return
match(p:Person {cid:1}) return p.name,ID(p)
-- 现有节点创建 没有属性的关系
match(p1:Person {cid:1}),(p2:Person{cid:2}) create(p1)-[r:Couple]->(p2)
-- 查询关系
match (p1:Person {cid:1})-[r:Couple]->(p2:Person) return p1,p2
-- 使用现有节点创建 有属性的关系
match (p1:Person {cid:1})-[r:Couple {price:1000}]->(p2:Person) return p1,p2 return r;
-- 新节点创建 没有属性的关系
create(p1:Person {cid:3})-[r:Couple]->(p2:Person {cid:4})
-- 新节点创建 有属性的关系
create(p1:Person {cid:3})-[r:Couple {price:2000}]->(p2:Person {cid:4})
WHERE和删除
match(p:Person) where p.price > 1000 return p
match p=(:Person {name:"joe"})-[r:Couple]-(:Person) return p;
-- 删节点
match(p:Person) where p.cid=2 delete p
-- 删关系
match p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person) delete r
-- 删属性
match(p:Person) where p.cid=2 remove p.name
-- 深度运算,查询深度最小1,最大2
match data=(na:Person {name:"joe"}-[*1..2]-(nb:Person) return data