MongoEngine不为人知的方法
之前发了个博客写的是MongoEngine的入门文档,在清楚了建表的字段类型,学会如何查询之后,我们来聊聊MongoEngine不常用但很有用的其他方法。
文章目录
1.get查询容错
# 查询某个用户时,get方法有则返回queryset,无则报错User.DoesNotExist
user = User.objects.get(name="xx")
# 为防止报错, 有则返回queryset,无则返回None
user = User.objects.filter(name="xx")
if user:
user = user[0]
# 或者
user = User.objects.filter(name="xx").first()
# 进一步优化
user = User.objects(name="xx").first()
2.with_id使用
# mongo默认id类型为ObjectId,所以使用id查询时,需将str转换为ObjectId
from bson import ObjectId
user = User.objects.get(id=ObjectId(user_id))
# 优化
user = User.objects.with_id(user_id)
3.filter中字符查询-contains使用
# contains包含,icontains包含(忽略大小写)
# 模糊检索时对象属性包含所查询字符,如name为abc,输入ab
user = User.objects.filter(name__contains=search_str)
4.不包含查询
这个功能让我找了好久…知道怎么写的时候眼泪掉下来
# 包含contains 不包含not__contains
# 姓名不包含aa的人
user = User.objects.filter(name__not__contains="aa")
5.list转querySet
# 多对多查询时,查询到某对象关联的列表集,进一步使用filter时报错非querySet
set_role = Role.objects.filter(pk__in=[i.pk for i in role_list if i])
6.querySet转dict
user = User.objects.get(name="xxx")
# 需⚠️的是,若将此功能作为结果集的serializer使用,不应该包含外键关联字段
# 用fields方法过滤指定字段也不起作用
user_dict = user.to_mongo().to_dict()
7.Serializer处理
# 自定义函数
# 序列化处理,排除指定字段
def m2d_exclude(obj, *args):
model_dict = obj.to_mongo().to_dict()
if args:
list(map(model_dict.pop, list(args)))
if "_id" in model_dict.keys():
model_dict["_id"] = str(model_dict["_id"])
return model_dict
# 序列化处理,只返回特定字段
def m2d_fields(obj, *args):
model_dict = obj.to_mongo().to_dict()
if args:
fields = [i for i in model_dict.keys() if i not in list(args)]
list(map(model_dict.pop, fields))
if "_id" in model_dict.keys():
model_dict["_id"] = str(model_dict["_id"])
return model_dict
调用
class Role(db.Document):
name = db.StringField(verbose_name="角色名称")
desc = db.StringField(verbose_name="职责描述")
permission = db.ListField(db.ReferenceField(Permission, reverse_delete_rule=4), verbose_name="权限")
staff = db.ListField(db.ReferenceField(Staff, reverse_delete_rule=4), verbose_name="关联员工")
role = Role.objects.get(name="管理员")
result = m2d_exclude(role, "permission", "staff")
# 或
result = m2d_fields(role, "name", "desc", "_id")
8. item_frequencies的使用
文档是这么写的:返回整个查询文档集中字段存在的所有项的字典及其对应的频率,即某字段所有值的集合(去重)和结果出现次数,简单来说就是group_by
想到的应用场景
-
一个班级所有人的数学成绩,不及格的多少人,60-70的多少人,80-90的多少人…
-
分类
使用:
9.scalar
获取所查询的字段值的列表
10.in_bulk
通过索引列表获取queryset
# 不使用in_bulk
# 通常情况,前端发送id列表
ids = data.json["ids"]
result = [Role.objects.with_id(i) for i in ids]
# 使用in_bulk
ids = data.json("ids")
ids = [ObjectId(i) for i in ids]
documents = Role.objects.in_bulk(ids)
results = [documents.get(obj_id) for obj_id in ids]
……还是不使用了吧