更多mongoengine库用法详见博文:
python中mongoengine库用法详解_IT之一小佬的博客-CSDN博客
官方文档:MongoEngine User Documentation — MongoEngine 0.25.0 documentation
1、 数据库结构定义
1.1 时间字段定义
DateTimeField类型:
create_time_utc = DateTimeField(default=datetime.utcnow())
create_time_now = DateTimeField(default=datetime.now())
也可以这样写,推荐:
create_time_utc = DateTimeField(default=datetime.utcnow)
create_time_now = DateTimeField(default=datetime.now)
DateField类型:
create_date_utc = DateField(default=datetime.utcnow().date)
create_date_now = DateField(default=datetime.now().date)
2、条件查询
2.1 比较运算符$in
in:表示在数组内
示例代码:
from model import StudentInfo, SexEnum
import random
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
# print(self.info)
def add_one_student(self):
"""新增一个学生信息"""
student = StudentInfo(
name=self.info['name'],
sex=random.choice([SexEnum.MAN, SexEnum.WOMAN]),
age=random.randint(10, 15),
teachers=self.info['teachers']
)
# print(student)
result = student.save()
return result
def get_one_student(self):
"""查询一个学生的信息"""
student_info = StudentInfo.objects.first()
# print(student_info)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
# print(student_all_info)
return student_all_info
def condition_query_in(self):
"""$in:在数组内"""
student_in = StudentInfo.objects.filter(teachers__in=["王老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 注意:这种情况下使用[0],若数据查询不到时会报错
student_in = StudentInfo.objects.filter(teachers__in=["王老师"])[0]
print(student_in, type(student_in))
print(student_in.name, student_in.sex, student_in.age, student_in.teachers)
print("*" * 100)
# 当列表中仅有一个值时,可以使用等号
student_in = StudentInfo.objects.filter(teachers=["孙老师"])[0]
print(student_in)
print(student_in.name, student_in.sex, student_in.age, student_in.teachers)
print("*" * 100)
# 当teachers字段中有一个值在列表中,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__in=["王老师", "孙老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 当teachers字段列表中第一个值在列表中时,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__in__0=["王老师", "孙老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 当teachers字段列表中第一个值等于某个值时,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__0="王老师")
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
return student_in
if __name__ == '__main__':
info = {"name": "王五", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
# obj.add_one_student()
# obj.get_one_student()
# obj.get_all_student()
obj.condition_query_in()
运行结果:
2.2 定义query自定义函数并继承
model.py:
from mongoengine import Document, connect, EnumField, StringField, IntField, ListField, DateTimeField, DateField
from enum import Enum
from datetime import datetime
# 连接到User数据库
# connect('user', host='192.168.124.104', port=27017)
connect('user', host='mongodb://root:88888888@192.168.124.49:27017/?authSource=admin')
class SexEnum(Enum):
MAN = '男'
WOMAN = '女'
class BaseFunc(object):
@classmethod
def query(cls, exception=False, **kwargs):
doc = cls.objects(**kwargs).first()
if doc is None:
if exception:
return '查询结果为空!'
return None
return doc
class StudentInfo(Document, BaseFunc):
"""学生信息"""
name = StringField(required=True, max_length=16, verbose_name='姓名')
sex = EnumField(enum=SexEnum, verbose_name='性别')
age = IntField(min_value=0, max_value=150, verbose_name='年龄')
teachers = ListField(StringField(max_length=150), verbose_name='老师们')
create_time_utc = DateTimeField(default=datetime.utcnow)
create_time_now = DateTimeField(default=datetime.now)
create_date_utc = DateField(default=datetime.utcnow().date)
create_date_now = DateField(default=datetime.now().date)
meta = {
# 指定文档的集合
'collection': 'students_info',
'ordering': ['-age'],
'strict': False
}
def __repr__(self):
return f'StudentInfo({self.name}, {self.sex}, {self.age}, {self.teachers})'
def __str__(self):
return self.__repr__()
main.py:
from model import StudentInfo, SexEnum
import random
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
def add_one_student(self):
"""新增一个学生信息"""
student = StudentInfo(
name=self.info['name'],
sex=random.choice([SexEnum.MAN, SexEnum.WOMAN]),
age=random.randint(10, 15),
teachers=self.info['teachers']
)
result = student.save()
return result
def get_one_student(self, name, exception=False):
"""查询一个学生的信息"""
student_info = StudentInfo.query(name=name, exception=exception)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
return student_all_info
if __name__ == '__main__':
info = {"name": "王五6", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
one_student = obj.get_one_student(name='王五4', exception=True)
print(one_student)
one_student = obj.get_one_student(name='王五41', exception=True)
print(one_student)
all_student = obj.get_all_student()
print(all_student)
运行结果:
3、更新数据
3.1 update()使用
update()是原子更新,使用时是局部更新。
示例代码:
from model import StudentInfo, SexEnum
import random
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
# print(self.info)
def add_one_student(self):
"""新增一个学生信息"""
student = StudentInfo(
name=self.info['name'],
sex=random.choice([SexEnum.MAN, SexEnum.WOMAN]),
age=random.randint(10, 15),
teachers=self.info['teachers']
)
# print(student)
result = student.save()
return result
def get_one_student(self):
"""查询一个学生的信息"""
student_info = StudentInfo.objects.first()
# print(student_info)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
# print(student_all_info)
return student_all_info
if __name__ == '__main__':
info = {"name": "王五", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
# obj.add_one_student()
one_student = obj.get_one_student()
print(one_student)
print(type(one_student))
one_student.update(age=20)
all_student = obj.get_all_student()
print(all_student)
运行结果:
3.2 类中自定义update()方法
示例代码:
from model import StudentInfo, SexEnum
import random
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
# print(self.info)
def add_one_student(self):
"""新增一个学生信息"""
student = StudentInfo(
name=self.info['name'],
sex=random.choice([SexEnum.MAN, SexEnum.WOMAN]),
age=random.randint(10, 15),
teachers=self.info['teachers']
)
# print(student)
result = student.save()
return result
def get_one_student(self):
"""查询一个学生的信息"""
student_info = StudentInfo.objects.first()
# print(student_info)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
# print(student_all_info)
return student_all_info
def update(self, name=None, sex=None, age=None):
"""更新一条数据"""
student_name = StudentInfo.objects(name=name).first()
if not student_name:
return f"{name}不存在!"
modify = False
if sex is not None and student_name.sex != sex:
student_name.sex = sex
modify = True
if age is not None and student_name.age != age:
student_name.age = age
modify = True
if modify:
student_name.save()
return self
if __name__ == '__main__':
info = {"name": "王五", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
# obj.add_one_student()
one_student = obj.get_one_student()
print(one_student)
print(type(one_student))
obj.update(name='王五4', age=26)
all_student = obj.get_all_student()
print(all_student)
运行结果:
3.3 集合类中定义封装update方法
model.py
from mongoengine import Document, connect, EnumField, StringField, IntField, ListField, DateTimeField, DateField
from enum import Enum
from datetime import datetime
# 连接到User数据库
# connect('user', host='192.168.124.104', port=27017)
connect('user', host='mongodb://root:88888888@192.168.124.49:27017/?authSource=admin')
class SexEnum(Enum):
MAN = '男'
WOMAN = '女'
class BaseFunc(object):
def update(self, **kwargs):
return self.update(**kwargs)
class StudentInfo(Document, BaseFunc):
"""学生信息"""
name = StringField(required=True, max_length=16, verbose_name='姓名')
sex = EnumField(enum=SexEnum, verbose_name='性别')
age = IntField(min_value=0, max_value=150, verbose_name='年龄')
teachers = ListField(StringField(max_length=150), verbose_name='老师们')
create_time_utc = DateTimeField(default=datetime.utcnow)
create_time_now = DateTimeField(default=datetime.now)
create_date_utc = DateField(default=datetime.utcnow().date)
create_date_now = DateField(default=datetime.now().date)
meta = {
# 指定文档的集合
'collection': 'students_info',
'ordering': ['-age'],
'strict': False
}
def raw_update(self, **kwargs):
return super().update(**kwargs)
def __repr__(self):
return f'StudentInfo({self.name}, {self.sex}, {self.age}, {self.teachers})'
def __str__(self):
return self.__repr__()
main.py
from model import StudentInfo
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
def get_one_student(self):
"""查询一个学生的信息"""
student_info = StudentInfo.objects.first()
# print(student_info)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
return student_all_info
if __name__ == '__main__':
info = {"name": "王五6", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
one_student = obj.get_one_student()
print(one_student)
one_student.raw_update(age=25)
one_student = obj.get_one_student()
print(one_student)
all_student = obj.get_all_student()
print(all_student)
运行结果:
3.4 原子更新操作
原子更新的语法类似于查询语法,但修饰符出现在字段之前,而不是之后。
- set– 设置一个特定的值
- set_on_insert– 仅当这是新文档时才设置 `需要添加 upsert=True`_
- unset– 删除特定值(自 MongoDB v1.3 起)
- max– 仅在值较大时更新
- min– 仅在值较小时更新
- inc– 将一个值增加给定的数量
- dec– 将一个值减少给定的量
- push– 将值附加到列表
- push_all– 将几个值附加到列表
- pop–根据值删除列表的第一个或最后一个元素
- pull– 从列表中删除一个值
- pull_all– 从列表中删除多个值
- add_to_set– 仅在不在列表中时才向列表添加值
- rename– 重命名键名
示例代码:
from model import StudentInfo
all_student_info = StudentInfo.objects.all()
print(all_student_info)
one_student_info = StudentInfo.objects(name="王五4").first()
print(one_student_info)
print(type(one_student_info))
# inc
StudentInfo.objects(name="王五4").update(inc__age=3)
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# dec
StudentInfo.objects(name="王五4").update(dec__age=2)
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# set
StudentInfo.objects(name="王五4").update(set__teachers__0="孙老师")
# StudentInfo.objects(name="王五4").update(teachers__0="王老师")
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# unset
StudentInfo.objects(name="王五4").update(unset__teachers__0="王老师")
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# push
StudentInfo.objects(name="王五4").update(push__teachers="董老师")
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
StudentInfo.objects(name="王五4").update(push__teachers=["张老师", "刘老师"])
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# push_all
StudentInfo.objects(name="王五4").update(push_all__teachers=["赵老师", "钱老师"])
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# pop
pop_ret = StudentInfo.objects(name="王五4").update(pop__teachers=1) # 删除最后一个
print(pop_ret)
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# pull
pop_ret = StudentInfo.objects(name="王五4").update(pull__teachers="董老师") # 删除符合条件的所有值
print(pop_ret)
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# pull_all
pop_ret = StudentInfo.objects(name="王五4").update(pull_all__teachers=["赵老师", "钱老师", "张老师"]) # 删除符合列表中条件的所有值
print(pop_ret)
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# add_to_set
StudentInfo.objects(name="王五4").update(add_to_set__teachers=["赵老师", "钱老师", "张老师", "孙老师"]) # 添加不存在的列表中的所有值
StudentInfo.objects(name="王五4").update(add_to_set__teachers="李老师") # 当存在时不添加,否则添加
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
# rename
StudentInfo.objects(name="王五4").update(rename__sex="gender")
one_student_info.reload() # the document has been changed, so we need to reload it
print(one_student_info)
运行结果:
注意:使用des时,注意min_value的设置值。
注意:如果未指定修饰符运算符,则默认值为$set. 所以下面的句子是相同的:
StudentInfo.objects(name="王五4").update(set__teachers__0="王老师")
StudentInfo.objects(name="王五4").update(teachers__0="王老师")
注意:使用rename时,直接把该条数据的键值给修改了。
附录:
model.py:
from mongoengine import Document, connect, EnumField, StringField, IntField, ListField, DateTimeField, DateField
from enum import Enum
from datetime import datetime
# 连接到User数据库
# connect('user', host='192.168.124.104', port=27017)
connect('user', host='mongodb://root:88888888@192.168.124.49:27017/?authSource=admin')
class SexEnum(Enum):
MAN = '男'
WOMAN = '女'
class BaseFunc(object):
@classmethod
def query(cls, exception=False, **kwargs):
doc = cls.objects(**kwargs).first()
if doc is None:
if exception:
return '查询结果为空!'
return None
return doc
def update(self, **kwargs):
return self.update(**kwargs)
class StudentInfo(Document, BaseFunc):
"""学生信息"""
name = StringField(required=True, max_length=16, verbose_name='姓名')
sex = EnumField(enum=SexEnum, verbose_name='性别')
age = IntField(min_value=0, max_value=150, verbose_name='年龄')
teachers = ListField(StringField(max_length=150), verbose_name='老师们')
create_time_utc = DateTimeField(default=datetime.utcnow)
create_time_now = DateTimeField(default=datetime.now)
create_date_utc = DateField(default=datetime.utcnow().date)
create_date_now = DateField(default=datetime.now().date)
meta = {
# 指定文档的集合
'collection': 'students_info',
'ordering': ['-age'],
'strict': False
}
def raw_update(self, **kwargs):
return super().update(**kwargs)
def __repr__(self):
return f'StudentInfo({self.name}, {self.sex}, {self.age}, {self.teachers})'
def __str__(self):
return self.__repr__()
main.py:
from model import StudentInfo, SexEnum
import random
class LearnMongoDBEngine(object):
def __init__(self, info):
self.info = info
# print(self.info)
def add_one_student(self):
"""新增一个学生信息"""
student = StudentInfo(
name=self.info['name'],
sex=random.choice([SexEnum.MAN, SexEnum.WOMAN]),
age=random.randint(10, 15),
teachers=self.info['teachers']
)
# print(student)
result = student.save()
return result
def get_one_student(self):
"""查询一个学生的信息"""
student_info = StudentInfo.objects.first()
# print(student_info)
return student_info
def get_one_student2(self, name, exception=False):
"""查询一个学生的信息"""
student_info = StudentInfo.query(name=name, exception=exception)
return student_info
def get_all_student(self):
"""查询所有学生的信息"""
student_all_info = StudentInfo.objects.all()
# print(student_all_info)
return student_all_info
def update(self, name=None, sex=None, age=None):
"""更新一条数据"""
student_name = StudentInfo.objects(name=name).first()
if not student_name:
return f"{name}不存在!"
modify = False
if sex is not None and student_name.sex != sex:
student_name.sex = sex
modify = True
if age is not None and student_name.age != age:
student_name.age = age
modify = True
if modify:
student_name.save()
return self
def condition_query_in(self):
"""$in:在数组内"""
student_in = StudentInfo.objects.filter(teachers__in=["王老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 注意:这种情况下使用[0],若数据查询不到时会报错
student_in = StudentInfo.objects.filter(teachers__in=["王老师"])[0]
print(student_in, type(student_in))
print(student_in.name, student_in.sex, student_in.age, student_in.teachers)
print("*" * 100)
# 当列表中仅有一个值时,可以使用等号
student_in = StudentInfo.objects.filter(teachers=["孙老师"])[0]
print(student_in)
print(student_in.name, student_in.sex, student_in.age, student_in.teachers)
print("*" * 100)
# 当teachers字段中有一个值在列表中,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__in=["王老师", "孙老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 当teachers字段列表中第一个值在列表中时,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__in__0=["王老师", "孙老师"])
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
print("*" * 100)
# 当teachers字段列表中第一个值等于某个值时,就会被查询出来
student_in = StudentInfo.objects.filter(teachers__0="王老师")
print(student_in, type(student_in))
for i in student_in:
print(i.name, i.sex, i.age, i.teachers)
return student_in
if __name__ == '__main__':
info = {"name": "王五", "teachers": ["孙老师"]}
obj = LearnMongoDBEngine(info)
# obj.add_one_student()
# obj.get_one_student()
# obj.get_all_student()
obj.condition_query_in()