python使用ODM控制Mongodb(MongoEngine)
1.安装pip install mongoengine2.连接数据库要连接一个 mongod实例, 需要用到connect()函数。分不同情况需提供不同的连接参数。2.1 默认情况指mongod运行在localhost且端口为27017只需要提供需要连接的数据库名即可:frommongoengineimportconnect connect(project1)2.2 mongod运行在其他服务器或者端口不为默认27107端口frommongoengineimportconnect connect(project1,host192.168.1.35,port12345)2.3 需要用户登陆验证frommongoengineimportconnect connect(project1,usernamewebapp,passwordpwd123,authentication_sourceadmin)2.4 URI连接方式将URI给host参数赋值frommongoengineimportconnect connect(project1,hostmongodb://localhost/database_name)注意如URI包含数据库名用户名或者密码将会覆盖相应参数的传值。如以下例子连接的数据库将会是production用户名为admin密码为qwerty。frommongoengineimportconnect connect(dbtest,usernameuser,password12345,hostmongodb://admin:qwertylocalhost/production)2.5 连接副本集frommongoengineimportconnect# Regular connectconnect(dbname,replicasetrs-name)# MongoDB URI-style connectconnect(hostmongodb://localhost/dbname?replicaSetrs-name)2.6 多数据库连接连接多个数据库可以使用 connect() 并设置别名参数alias如没有设置别名则默认为 “default” 。connect(dbtest01,aliastestdbA)connect(dbtest02,aliastestdbB)connect(dbtest03,aliastestdbC)也可以使用 register_connection() 进行多个数据库连接信息的存储。register_connection(aliasdefault,dbtest)当单独Document类需要调用特定数据库时只需要在meta的 db_alias 设置对应的数据库别名即可。classUser(Document):nameStringField()meta{db_alias:user-db}classBook(Document):nameStringField()meta{db_alias:book-db}classAuthorBooks(Document):authorReferenceField(User)bookReferenceField(Book)meta{db_alias:users-books-db}3. 上下文管理3.1 切换数据库使用switch_db提供需要切换数据库的类与所需切换到的数据库别名即可进行切换数据库。frommongoengine.context_managersimportswitch_dbclassUser(Document):nameStringField()meta{db_alias:user-db}withswitch_db(User,archive-user-db)asUser:User(nameRoss).save()# Saves the archive-user-db3.2 切换集合数据表使用switch_collection提供需要切换集合的类与所需切换到的集合名即可进行切换集合。frommongoengine.context_managersimportswitch_collectionclassGroup(Document):nameStringField()Group(nametest).save()# Saves in the default dbwithswitch_collection(Group,group2000)asGroup:Group(namehello Group 2000 collection!).save()# Saves in group2000 collection注意使用上下文管理之前需使用register_connection()或connect()登记需要使用到的数据库信息。4. 定义文件MongoEngine允许您为文档定义模式因为这有助于减少编码错误并允许在可能存在的字段上定义实用方法下面来一个给一个例子,要为文档定义模式请创建一个继承自其的类 Document。通过将字段对象作为类属性添加到文档类来指定字段frommongoengineimport*importdatetimeclassPage(Document):titleStringField(max_length200,requiredTrue)date_modifiedDateTimeField(defaultdatetime.datetime.utcnow)5.字段默认情况下字段不是必需的。要使字段成为必填字段请将字段的required关键字参数设置 为True。字段也可能有可用的验证约束max_length例如上面的示例中。字段也可以采用默认值如果没有提供值将使用默认值。默认值可以可选地是可调用的将被调用来检索该值例如在上面的示例中。可用的字段类型如下所示BinaryField 二进制数据字段 BooleanField ComplexDateTimeField DateTimeField DecimalField DictField DynamicField EmailField EmbeddedDocumentField EmbeddedDocumentListField FileField GridFS存储字段 FloatField GenericEmbeddedDocumentField GenericReferenceField GenericLazyReferenceField GeoPointField ImageField 图像文件存储区域 IntField ListField MapField ObjectIdField ReferenceField LazyReferenceField SequenceField SortedListField StringField URLField UUIDField PointField LineStringField PolygonField MultiPointField MultiLineStringField MultiPolygonField6.字段参数每个字段类型可以通过关键字参数进行定制。以下关键字参数可以在所有字段上设置db_field 默认无MongoDB字段名称。required 默认False如果设置为True并且该字段未在文档实例上设置ValidationError则在验证文档时将引发a 。default 默认无未为此字段设置值时使用的值。默认参数的定义遵循Python的一般规则这意味着在处理默认的可变对象时应该小心一些如in ListField或DictFieldclassExampleFirst(Document):# 默认是一个空列表valuesListField(IntField(),defaultlist)classExampleSecond(Document):valuesListField(IntField(),defaultlambda:[1,2,3])classExampleDangerous(Document):valuesListField(IntField(),default[1,2,3])unique 默认False如果为True则该集合中的任何文档都不会具有该字段的相同值。unique_with 默认无与此字段一起使用的字段名称或字段名称列表将不会具有相同值的集合中的两个文档。primary_key 默认False如果为True则使用此字段作为集合的主键。 DictField 和EmbeddedDocuments都支持作为文档的主键。如果设置该字段也可通过PK字段访问choices 默认无一个可迭代的例如列表元组或集合选项这个字段的值应该被限制到这个选项。#可以是值的嵌套元组存储在mongo中和人类可读的密钥SIZESSmall MMedium LLarge XLExtra Large XXL特大号classShirtDocument sizeStringField max_length3 choicesSIZE#或者是一个只包含值的平坦迭代器SIZESMLXLXXLclassShirtDocument sizeStringField max_length3 choicesSIZE **kwargs 可选的您可以提供额外的元数据作为任意附加关键字参数 但是您无法覆盖现有的属性。常用选项包括help_text和verbose_name通常由窗体和小部件库使用7.列表字段MongoDB允许存储项目列表。要想添加列表类型到 Document请使用ListField字段类型。ListField将另一个字段对象作为其第一个参数该参数指定列表中可以存储哪些类型元素classPage(Document):tagsListField(StringField(max_length50))8. 嵌入式文档MongoDB能够在其他文档中嵌入文档。可以为这些嵌入式文档定义概要就像它们可能用于常规文档一样。要创建嵌入式文档只需像往常一样定义一个文档但继承EmbeddedDocument而不是 DocumentclassComment(EmbeddedDocument):contentStringField()要将文档嵌入到另一个文档中请使用 EmbeddedDocumentField字段类型将嵌入的文档类作为第一个参数提供classPageDocument commentsListField EmbeddedDocumentField Comment comment1Comment contentGood work comment2Comment contentNice article pagePage comments[comment1 comment2]9.字典字段通常可以使用嵌入式文档而不是字典 - 通常建议使用嵌入式文档因为字典不支持验证或自定义字段类型。但是有时你不会知道你想要存储的结构; 在这种情况下DictField是合适的classSurveyResponse(Document):dateDateTimeField()userReferenceField(User)answersDictField()survey_responseSurveyResponse(datedatetime.utcnow(),userrequest.user)response_formResponseForm(request.POST)survey_response.answersresponse_form.cleaned_data()survey_response.save()字典可以存储复杂的数据其他字典列表对其他对象的引用所以是最灵活的可用字段类型10.引用字段要使引用字段可以存储到数据库中的其他文档可以使用 ReferenceField。传入另一个文档类作为构造函数的第一个参数然后将文档对象分配给该字段classUser(Document):nameStringField()classPage(Document):contentStringField()authorReferenceField(User)johnUser(nameJohn Smith)john.save()postPage(contentTest Page)post.authorjohn post.save()该User对象在幕后自动变为引用并在Page检索对象时解除引用。要添加一个ReferenceField引用正在定义的文档的引用请使用该字符串’self’代替文档类作为ReferenceField构造函数的参数。要引用尚未定义的文档请使用未定义文档的名称作为构造函数的参数classEmployee(Document):nameStringField()bossReferenceField(self)profile_pageReferenceField(ProfilePage)classProfilePage(Document):contentStringField()11.一对多与ListField如果通过引用列表实现一对多关系则引用将存储为DBRefs并且需要将对象的实例传递给查询classUser(Document):nameStringField()classPage(Document):contentStringField()authorsListField(ReferenceField(User))bobUser(nameBob Jones).save()johnUser(nameJohn Smith).save()Page(contentTest Page,authors[bob,john]).save()Page(contentAnother Page,authors[john]).save()# 查找所有由bob编写的网页此处用到了高级查询后面会介绍Page.objects(authors__in[bob])# 查找所有由bob和john编写的网页Page.objects(authors__all[bob,john])# 删除由bob编写的某篇文章根据某个id查找到的.Page.objects(id...).update_one(pull__authorsbob)# 把john添加到某篇文章根据某个id查找到的.Page.objects(id...).update_one(push__authorsjohn)12.处理引用文档的删除默认情况下MongoDB不检查数据的完整性因此删除其他文档仍然存在引用的文档将导致一致性问题。Mongoengine 的ReferenceField增加了一些功能来防范这些类型的数据库完整性问题为每个引用提供删除规则规范。通过reverse_delete_rule在ReferenceField定义上提供属性 来指定删除规则如下所示classProfilePage(Document):...employeeReferenceField(Employee,reverse_delete_rulemongoengine.CASCADE)#这个例子中的声明意味着当一个Employee对象被移除时ProfilePage引用该雇员的那个也被移除。如果删除了整批员工则所有链接的配置文件页面也会被删除它的值可以采用以下任何常量mongoengine.DO_NOTHING这是默认设置不会执行任何操作。删除速度很快但可能会导致数据库不一致或悬空引用。mongoengine.DENY如果仍存在对被删除对象的引用则拒绝删除。mongoengine.NULLIFY删除任何仍然指向被删除对象的对象字段使用MongoDB的“未设置”操作从而有效地消除关系。即删除了被引用的字段对引用它的字段无影响举个例子假如文章的作者字段采用的是引用字段那么作者一旦被删除那么由他写的文章仅仅是没有了作者他的文章都还在。mongoengine.CASCADE引用字段被删除则引用此字段的文档也会被删除举个例子假如文章的作者字段采用的是引用字段那么作者一旦被删除那么由他写的文章也都被删除。mongoengine.PULL从ListFieldReferenceField的任何对象的字段中删除对该对象的引用使用MongoDB的“拉”操作 。13. 通用参考字段第二种场景也存在 GenericReferenceField。这允许您引用任何类型的Document因此不会将 Document子类作为构造函数参数classLink(Document):urlStringField()classPost(Document):titleStringField()classBookmark(Document):bookmark_objectGenericReferenceField()linkLink(urlhttp://hmarr.com/mongoengine/)link.save()postPost(titleUsing MongoEngine)post.save()Bookmark(bookmark_objectlink).save()Bookmark(bookmark_objectpost).save()使用GenericReferenceFields的效率稍低于标准ReferenceFields所以如果只引用一种文档类型则更喜欢标准 ReferenceField14. 唯一性约束MongoEngine允许你通过提供uniqueTrue给Field构造函数来指定一个字段在集合中是唯一的。如果您尝试将与唯一字段具有相同值的文档保存为数据库的文档 NotUniqueError则会引发。您也可以使用下列方法指定多字段唯一性约束unique_with可以是单个字段名称也可以是字段名称的列表或元组classUser(Document):usernameStringField(uniqueTrue)first_nameStringField()last_nameStringField(unique_withfirst_name)跳过文档验证保存您也可以通过设置validateFalse调用save() 方法时跳过整个文档验证过程classRecipient(Document):nameStringField()emailEmailField()recipientRecipient(nameadmin,emailrootlocalhost)recipient.save()# 会产生一个 ValidationError 错误recipient.save(validateFalse)# 不会15.文档集合通过在文档中添加meta类字典属性我们可以更改数据集合的名称例如下方的例子我们把page改为了cmspageclassPage(Document):titleStringField(max_length200,requiredTrue)meta{collection:cmsPage}五). 索引您可以在集合上指定索引以加快查询速度。这是通过创建indexes在 meta字典中调用的索引规范列表完成的其中索引规范可以是单个字段名称包含多个字段名称的元组或包含完整索引定义的字典。顺序可以通过在字段名前加上 用于升序或-号用于降序来指定。请注意方向只对多字段索引很重要。文本索引可以通过在字段名前添加一个$来指定。散列索引可以通过在字段名前添加来指定classPage(Document):categoryIntField()titleStringField()ratingStringField()createdDateTimeField()meta{indexes:[title,$title,# 文本索引#title,# 散列索引(title,-rating),(category,_cls),{fields:[created],expireAfterSeconds:3600}]}如果采用字典那么以下选项可用fields 默认无 要索引的字段。与上述相同的格式指定。 cls 默认值True 如果您有多态模型可以继承并 allow_inheritance打开则可以配置索引是否应该将该_cls字段自动添加到索引的开头。 sparse 默认False 索引是否应该是稀疏的。 unique 默认False 索引是否应该是唯一的。 expireAfterSeconds 可选的 允许您通过设置以秒为单位的时间过期来自动将某个字段中的数据过期。六). 排序可以为您QuerySet使用的ordering属性 指定默认排序。排序将在QuerySet创建时应用 并且可以通过随后的order_by()覆盖fromdatetimeimportdatetimeclassBlogPost(Document):titleStringField()published_dateDateTimeField()meta{ordering:[-published_date]}blog_post_1BlogPost(titleBlog Post #1)blog_post_1.published_datedatetime(2010,1,5,0,0,0)blog_post_2BlogPost(titleBlog Post #2)blog_post_2.published_datedatetime(2010,1,6,0,0,0)blog_post_3BlogPost(titleBlog Post #3)blog_post_3.published_datedatetime(2010,1,7,0,0,0)blog_post_1.save()blog_post_2.save()blog_post_3.save()# 通过默认的排序降序获取第一篇文章# from BlogPost.meta.orderinglatest_postBlogPost.objects.first()assertlatest_post.titleBlog Post #3# 覆盖原来的默认排序规则采用升序first_postBlogPost.objects.order_by(published_date).first()assertfirst_post.titleBlog Post #1七). 文档继承要创建您定义的文档的专用类型您可以对其进行子类化并添加任何可能需要的额外字段或方法。 由于这是新类它不是Document的直接子类因此它不会存储在它自己的集合中; 它将使用与超类使用相同的集合。 这样可以更方便更高效地检索相关文档 - 您只需在元数据中将allow_inheritance设置为True即可。# Stored in a collection named pageclassPage(Document):titleStringField(max_length200,requiredTrue)meta{allow_inheritance:True}#这里要设置为True默认是False# Also stored in the collection named pageclassDatedPage(Page):dateDateTimeField()八). 抽象类如果您想为一组Document类添加一些额外的功能但您不需要或不需要继承的开销则可以使用该 abstract属性meta。这不会打开文档继承但可以让您保持代码干燥classBaseDocument(Document):meta{abstract:True,}defcheck_permissions(self):...classUser(BaseDocument):...现在User类将有权访问继承的check_permissions方法并且不会存储任何额外的_cls信息 这个特性在实际的web开发中作用很大

相关新闻

解锁音乐自由:ncmdumpGUI带你打破NCM格式枷锁

解锁音乐自由:ncmdumpGUI带你打破NCM格式枷锁

解锁音乐自由:ncmdumpGUI带你打破NCM格式枷锁 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾为网易云音乐下载的歌曲只能在特定客户端播放…

2026/10/16 6:51:12 阅读更多 →
Kimi K3 深度测评(一):2.8万亿参数、1M上下文背后,它到底是“全能王“还是“偏科生“?

Kimi K3 深度测评(一):2.8万亿参数、1M上下文背后,它到底是“全能王“还是“偏科生“?

Kimi K3 深度测评(一):2.8万亿参数、1M上下文背后,它到底是"全能王"还是"偏科生"?系列总览篇。本文不吹不黑,只做一件事:把 Kimi K3 的公开真实规格与基准数据摆上桌&#…

2026/10/17 4:04:48 阅读更多 →
微信小程序多张图片上传+springboot图片上传处理

微信小程序多张图片上传+springboot图片上传处理

微信小程序页面上传多张图片,带已上传图片回显,后台SpringBoot以jar包形式部署,上传保存到jar包同级目录 摘自最近写的小程序其中的一个功能片段 前端微信小程序上传图片 后台spring boot接取 因为要以jar包的形式进行部署 所以把文件保存业务改为保存在jar同级的目录 因为小程…

2026/10/13 18:36:54 阅读更多 →

最新新闻

集合论(二):从关系闭包到权限系统的工程落地

集合论(二):从关系闭包到权限系统的工程落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 4:05:00 阅读更多 →
OpenFeign多命名空间指定目标服务:根因、方案与实战

OpenFeign多命名空间指定目标服务:根因、方案与实战

用OpenFeign做微服务调用时,最头疼的往往不是配置繁琐,而是服务明明注册得好好的,一到运行时就给你报个UnknownHostException。尤其在多命名空间场景下,同一个服务可能同时部署在好几个namespace里,OpenFeign默认只认s…

2026/10/17 4:05:00 阅读更多 →
零基础程序员如何切入大模型赛道:从跑通到项目落地的实操指南

零基础程序员如何切入大模型赛道:从跑通到项目落地的实操指南

风口这个词,近两年在技术圈里出现的频率实在太高了。打开招聘软件,包含“大模型”“Agent”“RAG”字样的岗位越来越多,身边也有不少原本写业务代码的朋友开始焦虑:会不会这波浪潮跟自己没关系?对小白程序员来说&#…

2026/10/17 4:05:00 阅读更多 →
OCR表格扭曲矫正:几何约束驱动的轻量级图像复位技术

OCR表格扭曲矫正:几何约束驱动的轻量级图像复位技术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 4:05:00 阅读更多 →
编码助手自动记忆管理:Claude-Mem三层记忆机制与检索调优实战

编码助手自动记忆管理:Claude-Mem三层记忆机制与检索调优实战

1. 为什么自动记忆管理是编码助手的下一个刚需用过一段时间AI编码助手的人,大概都经历过这种尴尬:昨天刚跟助手讨论清楚的项目架构,今天开新会话它忘得一干二净;上周踩过的某个依赖版本坑,这周它又建议你装回那个有问题…

2026/10/17 4:05:00 阅读更多 →
从数字分身到AI员工:企业级Agent的可靠、可控与可审计实践

从数字分身到AI员工:企业级Agent的可靠、可控与可审计实践

OpenClaw 最近确实带起了一波“数字分身”热潮。我前后折腾了两周,最大的感受是:让 AI 模仿我的知识库、口吻和日常动作,确实能把不少琐碎工作自动化,还能用自然语言指挥它干活。但个人版玩得越爽,越能感觉到一个反差—…

2026/10/17 4:04:00 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →