一,mongo
mongoDB是一个基于分布式文件存储的数据库,C++编写,旨在为web应用提供可
拓展的高性能存储解决方案,是开源的。 mongoDB将数据存储为一个文档,数据结构由key——>value组成,mongo文档类似于json对象,字段可以包含其他文档,数组以及文档数组。
1.nosql数据库
2.c++语言编写的,基于分布式文档存储的数据库系统
3.将数据存储一个文档,数据结构由键值(key-value组成),mongoDB文档类似于json对象
字段可以包含其他文档,数组以及文档数组。
4. 可以在mongo中设置属性的索引,来实现更快的排序
5.可以使用update命令实现文档的更新
二,基础概念
dataBase 数据库;
collection:数据库/集合
document 数据记录行/文档
field: 数据字段/域
index:索引
primary key: 主键,MongoDB自动将_id字段设置为主键
对应的sql概念
表(Table)——>集合(collection)
行(Row)——> 文档(document)
列(Col)——> 字段(Field)
主键(primary key)——> 对象ID(ObjectId)
索引(Index)——> 索引(Index)
数组——>数组(Array)
mongo不支持表连接
mongoDB自动将_id字段设置为主键
三,常用查询
1.常用查询操作符
$gt 大于(great than)
$gte 对于等于 (great than equal)
$lt 小于 (less than)
$lte 小于等于(less than equal)
$ne 不等于(not equal)
2.文档
//创建文档
db.createCollection("ztk_user")
//查看所有的文档
show collections
//删除ztk_user
db.ztk_user.drop() //返回值是true
3.索引
//查询所有的索引
db.ztk_paper.getIndexes()
// 创建索引
// key 创建的索引字段,1 指定按照升序创建索引,如果降序指定为-1
db.ztk_paper.createIndex({year:1})
//查看索引大小
db.ztk_paper.totalIndexSize()
//删除指定索引集合
db.ztk_paper.dropIndex("year_1")
4.find查询
查询的语法,可以传入多个键,每个键以逗号分开。
>db.col.find({key1:value1, key2:value2})
db.getCollection('ztk_paper').find({用于过滤的条件},{返回限定条件})
如果一个字段被限定返回1,则代表该字段返回(也就是默认其他字段为0),所以其他未被限定的字段不会被返回。
_id比较特殊,无论怎么样,都会被返回。
5.模糊查询
用于比较两个表达式从mongDB集合中获取数据
查询 title 包含"教"字的文档:
db.col.find({title:/教/})
模糊查询
db.ztk_paper.find({name:/测试人民银行/},{name:1})
.limit (3)
db.ztk_paper.find({name:{$regex:"测试"}},{name:1})
.limit (3)
6.mongoDB or 条件
使用了关键字 $or ,语法格式
dg.ztk_paper.find({
$or:[{key1:value1},{key2:value2}]
})
例子:
db.ztk_paper.find({
$or:[{"status":2},{"type":2}]
}).sort({ _id: -1 })
.limit(100)
7.聚合分组
聚合的方法使用 aggregate,主要用于处理数据,比如平均数,求和等,并返回计算后的结果
$sum 计算总和
$avg计算平均值
$min 计算所有的最小值
$max 计算最大值
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
$match是分组的条件,用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理
按照指定条件分组
8.mongoDB关系
文档之间可以通过嵌入 和引用来建立联系
比如answerCard中嵌入paper对象信息
缺点:如果用户和用户地址不断增加,数据量不断变大,会影响读写性能。
引用式关系,这种方法可以把数据文档和用户地址数据文档分开,通过引用文档的ID字段建立关系。
{
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address_ids": [
ObjectId("52ffc4a5d85242602e000000"),
ObjectId("52ffc4a5d85242602e000001")
]
}
9.explain()查询性能分析
mongoDB 查询分析可以确保我们建立的索引是否有效,查询性能分析的重要工具。
10.mongoDB不支持事务
11.mongoDB 中的objectId
mongoDB 的objectId是一个12字节的BSON的类型数据,
前4个字节表示时间戳,接下来3个字节是机器表示码,紧接的两个是有进程ID组成(pid),最后三字节是
随机数。mongo中存储的文档必须是_id键,这个键可以是任何类型的,默认是ObjectId对象。
为什么_id 不是自增的,因为在服务器上同步自动增加主键值既费事又费时。
11.limit 和 skip 方法
mongoDB中需要读指定数量的数据记录,可以使用mongoDB 的limit方法。limit() 方法读取指定数量的数据外,还可以使用skip() 跳过指定数量的数据,skip 同样接受一个数字参数,作为跳过的记录条数。sort,limit,skip 放在一起的时候,执行的顺序是sort(),skip(),然后是limit
db.ztk_paper.find({})
.sort({_id:-1})
.skip(1)
.limit(4)
sort() 方法 可以指定排序的字段,1 为升序排序,-1 降序排序
如果skip的行数过大,查询将会很慢,因为skip是一条条的遍历。skip+limit 只适合
小量数据,大数据量效率低。
12.mongo分页
分页考虑的方法是 skip()+limit()实现,但是数量大的话,效率会比较低,所以在网上找另一种推荐的方法。
表结构如下:
mongo表的数据量是千万级别,每个记录都有createTime 字段,代表创建时间。
使用createTime 跳页的思路如下:
1.在当前页码中查询中最后一条记录的_id,计为last_id
2.把记录下来的last_id,作为查询记录,查询大于last_id的记录的作为下一页的内容
db.answer_card.find({_id:{$lt: NumberLong("1531087081051254188")}},{_id:1,createTime:1})
.sort({ createTime: -1 })
实现方法:
1.查询时候,所有的答题卡ID按照创建时间倒叙排序
2.定义cursor 为下一条记录的答题卡ID,第一页查询 令 cursor=long.Max_value 。这个时候
criteria.and("createTime").lt(createTime); 就查询出第一页的数据
查询出来第一页数据 ansCardList,返回值结果中设置下一页last 答题卡的ID
newCursor = answerCardList.get(answerCardList.size() - 1).getId();
3.第二页以及以后的每一页
把newCursor 作为参数查询,获取newCursor的创建时间,
接着查询
criteria.and("createTime").lt(createTime); 就查询出第一页的数据
就可以获取下一页的数据,以此类推。
参考博客: