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开发中作用很大

相关新闻

STM32F413RH与SE050协同实现物联网安全方案

STM32F413RH与SE050协同实现物联网安全方案

1. 物联网安全现状与SE050的定位在智能家居、工业4.0和智慧城市等场景中,设备间的数据交换频率呈指数级增长。去年某大型智能门锁厂商的密钥泄露事件导致数十万家庭安防系统暴露风险,这暴露出传统MCU在安全防护上的先天不足。STM32F413RH作为主流工业级M…

2026/7/28 15:17:22阅读更多 →
终极指南:三分钟让经典《暗黑破坏神2》在现代PC上焕发新生

终极指南:三分钟让经典《暗黑破坏神2》在现代PC上焕发新生

终极指南:三分钟让经典《暗黑破坏神2》在现代PC上焕发新生 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx D2DX是…

2026/7/28 15:17:22阅读更多 →
动态缠论识别引擎:3大算法突破重构量化交易分析

动态缠论识别引擎:3大算法突破重构量化交易分析

动态缠论识别引擎:3大算法突破重构量化交易分析 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 缠论分析一直是量化交易中的技术难题,传统人工识别效率低下且标准不一。CZSC缠论量…

2026/7/28 15:17:22阅读更多 →
【Springboot毕设全套源码+文档】基于SpringBoot的智慧物业管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

【Springboot毕设全套源码+文档】基于SpringBoot的智慧物业管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/28 16:29:50阅读更多 →
Add Binary (67)

Add Binary (67)

这也是经典题。忘了return需要是个string了。 另外忘了a,或者b过界之后,av,bv应该是0. 老了。 最后返回的时候,需要把list里面的数打包成string ‘’.join([str(i) for i in result]). result里面还是数,要重新搞个lis…

2026/7/28 16:29:50阅读更多 →
物联网设备电池寿命优化:NBM7100A与PIC32MZ的协同设计

物联网设备电池寿命优化:NBM7100A与PIC32MZ的协同设计

1. 项目背景与核心挑战在物联网设备和便携式电子产品的设计中,初级电池(不可充电电池)的寿命优化一直是个棘手问题。我曾参与过一个野外监测项目,设备需要在不更换电池的情况下持续工作5年以上。最初使用常规方案时,电…

2026/7/28 16:29:50阅读更多 →
linux shell 各种括号作用详解()、(())、[]、[[]]、{}

linux shell 各种括号作用详解()、(())、[]、[[]]、{}

一、小括号,圆括号() 1、单小括号 () ①命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令…

2026/7/28 16:29:50阅读更多 →
C++ noexcept关键字:从移动语义到容器性能优化的核心机制

C++ noexcept关键字:从移动语义到容器性能优化的核心机制

1. 项目概述:为什么我们需要 noexcept ? 在C的世界里,异常安全是一个老生常谈却又常谈常新的话题。当你辛辛苦苦写了一个类,确保它在抛出异常时资源不会泄漏(基本保证),甚至操作能保持原子性&…

2026/7/28 16:29:50阅读更多 →
AR-1106声源定位模组:TDOA算法原理与舵机联动控制的系统设计分析

AR-1106声源定位模组:TDOA算法原理与舵机联动控制的系统设计分析

背景:声源定位在智能感知系统中的需求在视频会议、监控跟随和机器人交互等应用中,系统不仅需要采集清晰的语音,还需要知道说话人在空间中的方位,以便驱动摄像头或机器人舵机将视野对准说话人。声源定位(Direction of A…

2026/7/28 16:27:49阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →