zoukankan      html  css  js  c++  java
  • MongoDB3 mongoengine(基本使用, ReferenceField, EmbeddedDocument, 时间段查询)

    文章参考:https://blog.csdn.net/xc_zhou/article/details/80837962

    mongoengine

    简介

    pymongo来操作MongoDB数据库,但是直接把对于数据库的操作代码都写在脚本中,这会让应用的代码耦合性太强,而且不利于代码的优化管理

    一般应用都是使用MVC框架来设计的,为了更好地维持MVC结构,需要把数据库操作部分作为model抽离出来,这就需要借助MongoEngine

    MongoEngine是一个对象文档映射器(ODM),相当于一个基于SQL的对象关系映射器(ORM)

    MongoEngine提供的抽象是基于类的,创建的所有模型都是类

    1基本使用

    #pip install mongoengine    # 安装
    
    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    
    users = Users.objects.all() #返回所有的文档对象列表
    for u in users:
        print("name:",u.name,",age:",u.age)

     保存文档

    from mongoengine import *
    connect('test',host='localhost',port=27017)
    class Users(Document):
        name = StringField(required=True,max_length=200)
        age = IntField(required=True)
    user1 = Users(
        name='zz',
        age=11
    )
    user1.save()
    print(user1.name)   # zz
    user1.name = 'zz11'
    user1.save()    # 保存后,age还是11
    print(user1.name)   # zz11

     查询10=<年龄<30的,按姓名排列

    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    user_search = Users.objects(age__gte=10, age__lt=33).order_by('name')
    for u in user_search:
        print("name:",u.name,",age:",u.age)

    查询10=<年龄<30的,按姓名倒序

    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    user_search = Users.objects(age__gte=10, age__lt=33).order_by('-name')
    for u in user_search:
        print("name:",u.name,",age:",u.age)

    查询name=zz11

    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    
    tmp = Users.objects(name="zz11")
    for u in tmp:
        print("name:",u.name,",age:",u.age)

    修改name=zz11的age加1

    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    tmp = Users.objects(name="zz11").update(inc__age=1)
    tmp = Users.objects(name="zz11")
    for u in tmp:
        print("name:",u.name,",age:",u.age)

    修改name=zz11的age设为55

    from mongoengine import *
    connect('test', host='localhost', port=27017)
    import datetime
    class Users(Document):
        name = StringField(required=True, max_length=200)
        age = IntField(required=True)
    
    tmp = Users.objects(name="zz11").update(set__age=55)
    tmp = Users.objects(name="zz11")
    for u in tmp:
        print("name:",u.name,",age:",u.age)

    2mongoengine基本用法实例:

    from mongoengine import *
    from datetime import datetime
    
    #连接数据库:test
    connect('test', host='localhost', port=27017)    # 连接本地test数据库
    # connect('test', host='127.0.0.1', port=27017, username='test', password='test')
    
    # Defining our documents
    # 定义文档user,post,对应集合user,post
    class User(Document):
        # required为True则必须赋予初始值
        email = StringField(required=True)
        first_name = StringField(max_length=50)
        last_name = StringField(max_length=50)
        date = DateTimeField(default=datetime.now(), required=True)
    
    # Embedded documents,it doesn’t have its own collection in the database
    class Comment(EmbeddedDocument):    # 嵌入文档,用于嵌入在其他文档EmbeddedDocumentField字段中
        content = StringField()
        name = StringField(max_length=120)
    
    class Post(Document):
        title = StringField(max_length=120, required=True)
        # ReferenceField相当于foreign key
        author = ReferenceField(User)    # 通过引用字段可以通过文档直接获取引用字段引用的那个文档
        tags = ListField(StringField(max_length=30))
        comments = ListField(EmbeddedDocumentField(Comment))
        # 允许继承
        meta = {'allow_inheritance': True}
    
    class TextPost(Post):
        content = StringField()
    
    class ImagePost(Post):
        image_path = StringField()
    
    class LinkPost(Post):
        link_url = StringField()
    
    # Dynamic document schemas:DynamicDocument documents work in the same way as Document but any data / attributes set to them will also be saved
    class Page(DynamicDocument): # 动态文档和普通文档一样,当有定义外的多余字段都能被保存
        title = StringField(max_length=200, required=True)
        date_modified = DateTimeField(default=datetime.now())

    添加数据

    john = User(email='john@example.com', first_name='John', last_name='Tao').save()
    ross = User(email='ross@example.com')
    ross.first_name = 'Ross'
    ross.last_name = 'Lawley'
    ross.save()
    
    comment1 = Comment(content='Good work!',name = 'LindenTao') #不会创建对应集合。
    comment2 = Comment(content='Nice article!')
    post0 = Post(title = 'post0',tags = ['post_0_tag'])
    post0.comments = [comment1,comment2]
    post0.save()    # 会多出_cls字段为Post,因为允许继承继承,_cls会标识出对象所属的类
    
    post1 = TextPost(title='Fun with MongoEngine', author=john)       # john必须保存后才能用  john.save()
    post1.content = 'Took a look at MongoEngine today, looks pretty cool.'
    post1.tags = ['mongodb', 'mongoengine']
    post1.save()    # 保存于post集合下,author字段为对象ObjectId("5fd8d55b353560e1260a451e")
    
    post2 = LinkPost(title='MongoEngine Documentation', author=ross)    # ross必须保存后才能用  ross.save()
    post2.link_url = 'http://docs.mongoengine.com/'
    post2.tags = ['mongoengine']
    post2.save()  # _cls字段为Post.LinkPost
    
    # 创建一个page集合,并且添加一个tags字段
    page = Page(title='Using MongoEngine')
    page.tags = ['mongodb', 'mongoengine']
    page.save()

    创建了三个集合:user,post,page

    查看数据

    # 查看数据
    for post in Post.objects:
        print post.title
        print '=' * len(post.title)
    
        if isinstance(post, TextPost):
            print post.content
    
        if isinstance(post, LinkPost):
            print 'Link:', post.link_url
    
    # 通过引用字段直接获取引用文档对象    
    for post in TextPost.objects:
        print post.content
        print post.author.email  
    au = TextPost.objects.all().first().author
    print au.email
    
    # 通过标签查询    
    for post in Post.objects(tags='mongodb'):
        print post.title   
    num_posts = Post.objects(tags='mongodb').count()
    print 'Found %d posts with tag "mongodb"' % num_posts
    
    # 多条件查询(导入Q类) 
    User.objects((Q(country='uk') & Q(age__gte=18)) | Q(age__gte=20))   
    
    # 更新文档
    ross = User.objects(first_name = 'Ross')  # 所有first_name为Ross的对象
    # ross = User.objects.filter(first_name = 'John')    # 所有first_name为Ross的对象   和上面作用相同
    ross.update(date = datetime.now()) 
    User.objects(first_name='John').update(set__email='123456@qq.com')
    //对 lorem 添加商品图片信息
    lorempic = GoodsPic(name='l2.jpg', path='/static/images/l2.jpg')
    lorem = Goods.objects(id='575d38e336dc6a55d048f35f')
    lorem.update_one(push__pic=lorempic)
    # 删除文档
    ross.delete() # 删除所有ross对象

    3基本使用

    from mongoengine import *
    from datetime import datetime
    # 连接数据库
    connect('blog')   # 连接本地blog数据库
    # 如需验证和指定主机名
    # connect('blog', host='192.168.3.1', username='root', password='1234')
    
    # 定义分类文档
    class Categories(Document):
        ' 继承Document类,为普通文档 '
        name = StringField(max_length=30, required=True)
        artnum = IntField(default=0, required=True)
        date = DateTimeField(default=datetime.now(), required=True)

    插入

    cate = Categories(name="Linux")   # 如果required为True则必须赋予初始值,如果有default,赋予初始值则使用默认值
    cate.save() # 保存到数据库

    查询和更新

    文档类有一个 objects 属性.我们使用它来查询数据库.

    # 返回集合里的所有文档对象的列表
    cate = Categories.objects.all()
    
    # 返回所有符合查询条件的结果的文档对象列表
    cate = Categories.objects(name="Python")
    # 更新查询到的文档:
    cate.name = "LinuxZen"
    cate.update()
    查询数组 默认查询数组"="代表的意思是in:
    class Posts(Document):
        artid = IntField(required=True)
        title = StringField(max_length=100, required=True)
        content = StringField(required=True)
        author = ReferenceField(User)
        tags = ListField(StringField(max_length=20, required=True), required=True)
        categories = ReferenceField(Categories), required=True)
        comments = IntField(default=0, required=True)
    
    # 将会返回所有tags包含coding的文档
    Posts.objects(tags='coding')

    ReferenceField 引用字段:

    通过引用字段可以通过文档直接获取引用字段引用的那个文档:

    class Categories(Document):
        name = StringField(max_length=30, required=True)
        artnum = IntField(default=0, required=True)
        date = DateTimeField(default=datetime.now(), required=True)
    
    class Posts(Document):
    
        title = StringField(max_length=100, required=True)
        content = StringField(required=True)
        tags = ListField(StringField(max_length=20, required=True), required=True)
        categories = ReferenceField(Categories)

    插入引用字段

    cate =Categories(name="Linux")
    cate.save()
    post = Posts(title="Linuxzen.com", content="Linuxzen.com",tags=["Linux","web"], categories=cate)
    post.save()

    通过引用字段直接获取引用文档对象

    一般文档查询会返回一个列表(尽管只有一个结果),我们想要获得一个文档对象可以使用索引获取第一个文档对象,但是mongoengine建议使用first()来获取第一个:

    >>> cate = Posts.objects.all().first().categories
    >>> cate
    
    >>> cate.name
    u'Linux'

    查询包含Linux分类的文章

    >>> cate = Categories.objects(name="Linux").first()
    >>> Posts.objects(categories=cate)

    EmbeddedDocument 嵌入文档

    继承EmbeddedDocument的文档类就是嵌入文档,嵌入文档用于嵌入其他文档的EmbeddedDocumentField 字段,比如上面例子的tags字段如果改成嵌入文档的话可以将Posts文档类改成如下方式:

    class Tags(EmbeddedDocument):  # 定义Tags嵌入文档类
        name = StringField()
        date = DateTimeField(default=datetime.now())
    
    class Posts(Document):
        title = StringField(max_length=100, required=True)
        content = StringField(required=True)
        tags = ListField(EmbeddedDocumentField('Tags'),required=True)   # Tags要定义在此类上方
        categories = ReferenceField(Categories)

    插入Posts文档中的Tags

    >>> tag = Tags(name="Linuxzen")
    >>> post = Posts(title="Linuxzen.com", content="Linuxzen.com", tags=[tag], categories=cate)
    >>> tag = Tags(name="mysite")
    >>> post.tags.append(tag)
    >>> post.save()
    >>> tags = post.tags
    >>> for tag in tags:
    print(tag.name)
    
    Linuxzen
    mysite

    时间段查询

    # start = datetime(int(year), int(month), 1)
    start = datetime(2020, 11, 1)
    end = datetime(2020, 12, 18)
    # tags__date tags字段下的date字段
    articles = Posts.objects(tags__date__gte=start, tags__date__lt=end).order_by('-date')

    分片

    slice用于分片

    # comments - skip 5, limit 10
    Page.objects.fields(slice__comments=[5, 10])
    
    # 也可以使用索引值分片
    
    # limit 5
    users = User.objects[:5]
    
    # skip 5
    users = User.objects[5:]
    
    # skip 10, limit 15
    users = User.objects[10:15]

    使用原始语句查询

    如果想使用原始的pymongo查询方式可以使用__raw__操作符 Page.objects(raw={‘tags’:‘coding’}) 使用i n c 和 inc和inc和set操作符

    # 更新嵌入文档comments字段by的值为joe的文档字段votes增加1
    Page.objects(comments_by="joe").update(inc__votes=1)
    
    # 更新嵌入文档comments字段by的值为joe的文档字段votes设置为1
    Page.objects(comments_by="joe").update(set__votes=1)

    其他技巧

    #查询结果转换成字典
    users_dict = User.objects().to_mongo()
    
    # 排序,按日期排列
    user = User.objects.order_by("date")
    
    # 按日期倒序
    
    user = User.objects.order_by("-date")

    高级用法参考:https://blog.csdn.net/weixin_42042680/article/details/87909424

  • 相关阅读:
    JS常见异常
    Spring boot 的 @Value注解读取配置文件中的00开头的字符串
    常用网址
    IntelliJ使用教程
    eclipse
    swagger
    Mybatis
    Linux常用命令
    阿里云短信
    Flink Checkpoint-轻量级分布式快照
  • 原文地址:https://www.cnblogs.com/ludingchao/p/14143196.html
Copyright © 2011-2022 走看看