You are viewing a single comment's thread from:

RE: PyMongo开发指南

in #starnote • 4 days ago (edited)
from datetime import datetime
from mongoengine import (
    Document, EmbeddedDocument,
    StringField, IntField, DateTimeField, 
    ListField, EmbeddedDocumentField, ReferenceField,
    connect
)

# ==========================================
# 1. 建立与 MongoDB 的连接
# ==========================================
# 连接到本地的 'blog_database' 数据库
connect(db='blog_database', host='mongodb://localhost:27017/')

# ==========================================
# 2. 定义数据模型(Schema)
# ==========================================

# 嵌入式文档(Embedded Document):用于文章底部的评论
class Comment(EmbeddedDocument):
    user_name = StringField(required=True, max_length=50)
    content = StringField(required=True)
    # created_at = DateTimeField(default=datetime.utcnow)
    created_at = DateTimeField(default=lambda: datetime.now(timezone.utc), required=True)


# 主文档(Document):用户表
class User(Document):
    name = StringField(required=True, max_length=50)
    email = StringField(required=True, unique=True)
    age = IntField(min_value=0)
    
    meta = {'collection': 'users'}  # 映射到 MongoDB 的 'users' 集合

# 主文档(Document):文章表(包含关联关系与嵌入式文档)
class Post(Document):
    title = StringField(required=True, max_length=120)
    content = StringField(required=True)
    author = ReferenceField(User, required=True)  # 外键引用:关联 User 文档
    tags = ListField(StringField(max_length=30))  # 列表字段:标签
    comments = ListField(EmbeddedDocumentField(Comment))  # 嵌套评论列表
    # created_at = DateTimeField(default=datetime.utcnow)
    created_at = DateTimeField(default=lambda: datetime.now(timezone.utc), required=True)


    meta = {'collection': 'posts'}  # 映射到 'posts' 集合


# ==========================================
# 3. 增、删、改、查(CRUD)业务逻辑
# ==========================================
def main():
    print("=== 1. 【增】Create 操作 ===")
    # 创建并保存用户
    user1 = User(name="张三", email="[email protected]", age=28)
    user1.save()  # 写入数据库
    
    user2 = User(name="李四", email="[email protected]", age=32)
    user2.save()

    # 创建并保存文章(关联张三,并添加标签和评论)
    post1 = Post(
        title="MongoEngine 快速入门",
        content="这是一篇关于如何使用 Python 和 MongoEngine 操作 MongoDB 的文章。",
        author=user1,
        tags=["Python", "MongoDB", "Database"],
        comments=[
            Comment(user_name="李四", content="写得非常好!")
        ]
    )
    post1.save()
    print(f"成功创建文章: {post1.title}, ID: {post1.id}")


    print("\n=== 2. 【查】Read 操作 ===")
    # 2.1 查询单个文档 (get 或 objects().first())
    found_user = User.objects(name="张三").first()
    print(f"查找到用户: {found_user.name}, 邮箱: {found_user.email}")

    # 2.2 条件查询与关联查询 (objects 配合条件过滤)
    # 查找标签包含 "Python" 的文章
    python_posts = Post.objects(tags="Python")
    for p in python_posts:
        print(f"文章标题: {p.title}")
        print(f"文章作者(自动触发引用填充): {p.author.name}")  # ReferenceField 会自动 Dereference


    print("\n=== 3. 【改】Update 操作 ===")
    # 3.1 实例修改并保存
    found_user.age = 29
    found_user.save() # 执行更新
    print(f"更新后张三的年龄: {User.objects(name='张三').first().age}")

    # 3.2 使用 update() 方法直接在数据库中批量/原子更新
    Post.objects(title="MongoEngine 快速入门").update(
        push__tags="ODM",  # 向 tags 列表追加一个元素
        set__content="更新后的文章内容:更详细的 MongoEngine 教程。" # 修改普通字段
    )
    updated_post = Post.objects(title="MongoEngine 快速入门").first()
    print(f"更新后的标签: {updated_post.tags}")
    print(f"更新后的内容: {updated_post.content}")


    print("\n=== 4. 【删】Delete 操作 ===")
    # 4.1 删除单个文档的实例
    target_user = User.objects(name="李四").first()
    target_user.delete()

    # 4.2 通过条件直接删除多个文档
    deleted_count = User.objects(name="李四").delete()
    print(f"已删除用户数量: {deleted_count}")
    print(f"剩余用户总数: {User.objects.count()}")

if __name__ == "__main__":
    main()

增删改查(CRUD)实现细节:
Create(增):实例化定义好的模型类(如 User(...)),然后调用 .save() 方法即可写入数据库。
Read(查):所有查询的入口都是 .objects(QuerySet 管理器)。
支持链式调用和丰富查询符,例如 User.objects(age__gte=18) 对应 MongoDB 的 { "age": { "$gte": 18 } }。
Update(改):对象级修改:直接修改对象的属性后调用 .save()。
原子更新符(QuerySet Update):使用 .update() 配合操作符(如 set__xxx、push__xxx、inc__xxx 等),直接在数据库层面高效更新,避免全量传输。
Delete(删):既可以对查询出来的对象调用 .delete(),也可以直接通过 .objects(...).delete() 批量删除。