MongoDB高级操作
.MongoDB的权限管理
为什么要设置权限管理
刚安装完毕的mongodb默认不适用权限认证方式启动,然而公网运行系统需要设置权限以保证数据安全MongoDB的权限管理方案
①mongodb没有默认管理员账号,需要添加管理员账号,开启验证
②用户只能在用户所在的数据库登录
③管理员账号可以管理所有数据库-
开启权限认证的方式
权限认证默认是关闭的①在启动数据库的时候添加--auth参数
sudo mongod --auth②在配置文件中添加auth = true,然后加载配置文件启动
mongodb创建用户
所有的用户都必须使用管理员账户创建
use admin 创建管理员用户使用的数据库
选择数据库后使用相应方法创建用户及权限
db.createUser({
user:”用户名”,
pwd:”密码”,
roles:[{role:”权限”,db:”数据库”}]
})
roles为权限设置的文档,文档中db为指定的数据库, role为权限(最常用的为root,read,readWrite)
mongodb创建用户
查看已经创建的用户权限
show users
use admin
db.system.users.find()
数据库权限的认证
use dbname
db.auth(user,pwd)
删除某一用户及权限
db.dropUser(用户名)
MongoDB的聚合运算
为什么要进行聚合运算
传统的查询运算知识将符合条件的数据放到结果集中,而聚合运算则将数据聚合到一起,然后通过管道做后续操作
如何进行聚合运算实现聚合运算的方法� db.colname.aggregate([ {管道 : {表达式}} ])
聚合运算是与管道配合使用的,管道是可以有多种的,聚合之后的数据会依次经过管道
- 常见管道
$match
①$match实现在聚合中进行查找操作,实现的功能同find()
②与find()操作的区别在与查询结果可以进行后续操作,而find不可以
db.colname.aggregate({$match:{key:{$gt:n}}})
查找key的值大于n的数据,前面的运算符在这里都可以使用
$project
功能类似于查询之后的投影操作
db.colname.aggregate(
{$match:{key:{$gt:n}}},
{$project:{_id:0}}
)
使用match进行比对过滤之后的结果经过project进行字段筛选之后再输出出来
$limit
①功能同查询之后的limit操作,返回规定的数据量
db.colname.aggregate(
{$match:{key:{$gt:n}}},
{$limit:n}
)
$skip
跳过指定数量的文档
db.colname.aggregate(
{$match:{key:{$gt:n}}},
{$skip:n}
)
在这里需要注意的是skip与limit的配合使用与find中是不同的,管道是依次执行的,需要根据业务需要进行配置
$sort
功能通find的排序操作,对数据进行排序
db.colname.aggregate(
{$match:{key:{$gt:n}}},
{$sort:{key1:1,key2:-1}}
)
$unwind
拆分字段值为列表的字段
db.colname.aggregate(
{$match:{key:{$gt:n}}},
{$unwind:”$key”}
)
不包含该字段的数据
MongoDB的索引
为什么要使用索引
索引可以提升查询速度,提升数据库查询的性能索引的优点点与缺点:
优点:
提高数据的查询速度
缺点:
牺牲了数据库的插入和更新速度如何查看语句执行情况
在执行语句之后追加explain(),并且提供参数executionStats
db.colname.find(query).explain(‘executionStats’)
索引的相关操作
查看已存在的索引
db.colname.getIndexes()
创建索引
索引创建的通用规则:
①创建索引使用的文档中键为设置索引的字段,值为1表示索引按照升序存储,值为-1则表示索引按照降序存储
②当有大量数据时,创建索引会非常缓慢,因此可以后台创建索引,在创建索引的时候添加{background:true}
单一索引
db.colname.ensureIndex({key:1},{background:true})
联合索引
db.colname.ensureIndex({key1:1,key2:1}
创建联合索引之后,可以使用key1或者key1,key2的查询进行查找
唯一索引
db.colname.ensureIndex({key:1},{“unique”:true})
注意事项:
①当创建一个key为唯一索引时,新插入的数据如果key的值与已存在的数据相同,则会报错。
②当对已存在数据的集合创建唯一索引时,可能会因为重复,导致创建不成功,使用dropDups可以删除重复文档,但是我们一般不建议使用
db.colname.ensureIndex({key:1},{“unique”:true,”dropDups”:true})
查询时强制使用索引
db.colname.find({key1:value}).hint(索引文档)
删除索引
db.colname.dropIndex({key:1})
查询优化器
单索引
当查询的key正好为设置的索引的时候,优化器直接使用索引
复合索引
①当有若干个索引能适合查询用到的key时,优化器会同时并行使用索引进行查询,选择最快索引
②优化器会定期或定查询次数重新进行最有索引的筛选
索引与全表扫描的对比选择
MongoDB的备份与恢复
数据的备份
为什么进行数据备份?
数据备份指的是将数据备份到指定的目录,并在需要的时候进行恢复,一般用于灾难处理
如何进行数据备份?
mongodump -h host -d dbname -o directionary
将指定的数据库备份到指定的目录中如何进行数据恢复?
mongorestore -h host -d dbname --dir directionary
数据的导出与导入
为什么进行数据的导出遇导入?
数据库中的数据在与其他平台和应用进行交互时需要按照指定格式导出交给后续步骤进行处理
如何进行数据备份?
mongoexport -d dbname -c colname -type json/csv –f file1,file2,file… -o filename
将指定的结合中的数据导出成文件如何进行数据导入?
mongoimport -d dbname -c colname filename
Python与MongoDB的交互
MongoDB的ORM
安装
安装成功后,可以测试。
如何连接数据库
连接本地的数据库用第一个方式就可以啦。
先启动MongoDB服务,然后连接,
import mongoengine
from mongoengine import connect
connect(‘students’)
ORM 模型的介绍
from mongoengine import connect,Document,EmbeddedDocument,\
StringField,IntField,FloatField,ListField,EmbeddedDocumentField
connect('students')
SEX_CHOICES = (
('male','男'),
('female','女'),
)
class Grade(EmbeddedDocument):
''' 成绩 '''
name = StringField(required=True)
score = FloatField(required=True)
# 最后要把它关联进去
class Student(Document):
name = StringField(max_length=32,required=True)
age = IntField(required=True)
sex = StringField(choices=SEX_CHOICES,required=True)
grade = FloatField()
address = StringField()
# 下面需要声明一个分数,由于有科目所以string类型搞不定
# 嵌套一个
grades = ListField(EmbeddedDocumentField(Grade))
新增数据
从上图可以看出可以通过变动的DynamicDocument 活动的文档来添加属性。
查询数据
减号代表倒序排列。
以年龄排序,使用get获取数据,发现多条数据
报错,是三条数据,所以错啦。
也可以重新制定排序
修改、删除数据
通过修改器,两个下划线。
大于16年龄
完整的代码:
from mongoengine import connect,Document,EmbeddedDocument,\
StringField,IntField,FloatField,ListField,EmbeddedDocumentField,DynamicDocument
connect('students')
SEX_CHOICES = (
('male','男'),
('female','女'),
)
class Grade(EmbeddedDocument):
''' 成绩 '''
name = StringField(required=True)
score = FloatField(required=True)
# 最后要把它关联进去
class Student(DynamicDocument):
name = StringField(max_length=32,required=True)
age = IntField(required=True)
sex = StringField(choices=SEX_CHOICES,required=True)
grade = FloatField()
address = StringField()
# 下面需要声明一个分数,由于有科目所以string类型搞不定
# 嵌套一个
grades = ListField(EmbeddedDocumentField(Grade))
#remark = StringField()
#这里不指定连接数据表名,根据类名自动创建
meta = {
'collection':'students',
'ordering':['-age']
}
class TestMongoEngine(object):
def add_one(self):
''' 添加一条数据到数据库 '''
yuwen = Grade(
name = '语文',
score = 90)
shuxue = Grade(
name = '数学',
score = 100)
stu_obj = Student(
name='张三5',
# 年龄是必须填写的,不填写报错
age = 17,
sex = 'male',
grades = [yuwen,shuxue]
)
stu_obj.remark = 'ramark'
stu_obj.save()
return stu_obj
def get_one(self):
'''查询一条数据'''
return Student.objects.first()
def get_more(self):
'''查询多条数据'''
return Student.objects.all()
def get_from_id(self,oid):
'''根据id查询数据'''
# z这里也可以用get
return Student.objects.filter(pk=oid).first()
def update(self):
'''修改数据'''
# 修改所有的男生年龄,增加10岁
#return Student.objects.filter(sex='male').update(inc__age = 10)
# 修改一条数据
return Student.objects.filter(sex='male').update_one(inc__age=100)
def delete(self):
'''删除数据 '''
# 删除一条数据
#return Student.objects.filter(sex='male').first().delete()
# 删除多条数据
return Student.objects.filter(sex='male').delete()
def main():
obj = TestMongoEngine()
# rest = obj.add_one()
# print(rest.pk)
# 返回的是对像
# rest = obj.get_one()
# print(rest.id)
# print(rest.name)
# rows = obj.get_more()
# for row in rows:
# print(row.name)
# rest = obj.get_from_id('5b272b2dbb07651ad02a143e')
# if rest:
# print(rest.id)
# print(rest.name)
# rest = obj.update()
# print(rest) # 打印的行数 3
rest = obj.delete()
print(rest) # 打印的行数 3
if __name__ == '__main__':
main()
网易新闻实战
依赖安装
更多详情请点击官网http://flask-mongoengine.readthedocs.io/en/latest/
新闻前台
然后,新闻的模型,连接数据库。
通过flask-mongoengine
在MongoDB数据库中插入一些新的数据,
切换到mongo_news数据库,
下面定义模型,新闻,图片是准备好的。
还有一些评论,可以做些扩展,类似学生的分数。
最后制定collection
下面做前台的展现,首先引入
上面的要修改一下,否则页面的内容都是一样的
前台