zoukankan      html  css  js  c++  java
  • MongoEngine 中文文档 系列教程 User Guide( 四)

    Document类有一个objects 属性,用来访问在数据库中跟这个类有关的数据。这个objects 属性其实是一个QuerySetManager ,它会创建和返回访问的一个新的 QuerySet。这个QuerySet 可以是在数据库中取出的重复的Document:

    [python] 
     
    1. # Prints out the names of all the users in the database  
    2. for user in User.objects:  
    3.     print user.name  

    查询过滤 
    可以通过使用 QuerySet  对象的关键字参数来对数据查询进行过滤,关键字查询中的键只想你想要查询的document:

    [python] 
     
    1. # This will return a QuerySet that will only iterate over users whose  
    2. # 'country' field is set to 'uk'  
    3. uk_users = User.objects(country='uk')  

    对于内嵌document的字段可以使用双下划线的的语法来进行访问:

    [python]
     
    1. # This will return a QuerySet that will only iterate over pages that have  
    2. # been written by a user whose 'country' field is set to 'uk'  
    3. uk_pages = Page.objects(author__country='uk')  

    查询操作符 
    在查询中也可以使用操作符,只要将其加在关键子的双下划线之后即可:

    [python]
     
    1. # Only find users whose age is 18 or less  
    2. young_users = Users.objects(age__lte=18)  

    可用的操作符如下: 

      • ne – 不等于
      • lt – 小于
      • lte – 小于等于
      • gt – 大于
      • gte – 大于等于
      • not – 使其检查的反面,需要使用在其他操作符之前(e.g. Q(age__not__mod=5))
      • in – 值在list里面
      • nin – 值不在list里面
      • mod – value % x == y
      • all – list里面所有的值
      • size – 这个array的大小
      • exists – 存在这个值

        一下操作符在需要进行正则检查的时候是比较快捷的方法:

      • exact – 字符串型字段完全匹配这个值
      • iexact – 字符串型字段完全匹配这个值(大小写敏感)
      • contains – 字符串字段包含这个值
      • icontains –字符串字段包含这个值(大小写敏感)
      • startswith – 字符串字段由这个值开头
      • istartswith –字符串字段由这个值开头(大小写敏感)
      • endswith – 字符串字段由这个值结尾
      • iendswith –字符串字段由这个值结尾(大小写敏感)
      • match – 使你可以使用一整个document与数组进行匹配查询list
        对于大多数字段,这种语法会查询出那些字段与给出的值相匹配的document,但是当一个字段引用 ListField 的时候,而只会提供一条数据,那么包含这条数据的就会被匹配上: 
        [python] 
         
        1. class Page(Document):  
        2.     tags = ListField(StringField())  
        3.   
        4. # This will match all pages that have the word 'coding' as an item in the  
        5. # 'tags' list  
        6. Page.objects(tags='coding')  
        可以通过list的位置来进行查询,你可以使用一个数字来作为查询操作符,例子如下:
        [python] 
         
        1. Page.objects(tags__0='db')  
        如果你只是想取出list中的一部分,例子如下:
        [python] 
         
        1. # comments - skip 5, limit 10  
        2. Page.objects.fields(slice__comments=[5, 10])  
        更新document的时候,如果你不知道在list中的位置,你可以使用 $ 这个位置操作符
        [python] 
         
        1. Post.objects(comments__by="joe").update(**{'inc__comments__$__votes': 1})  
        可是,如果这种映射不能正常工作的时候可以使用大写 S 来代替:
        [python]
         
        1. Post.objects(comments__by="joe").update(inc__comments__S__votes=1)  
        2.   
        3. .. note:: Due to Mongo currently the $ operator only applies to the first matched item in the query.  
        原始查询
        你可以使用一个原始的 pymongo 语句来进行查询,这样可以进行原始的完整查询,使用__raw__ 参数: 
        [python]
         
        1. Page.objects(__raw__={'tags': 'coding'})  
        限制和跳过结果
        就像传统的ORM一样,你有时候需要限制返回的结果的数量,或者需要跳过一定数量的结果。QuerySet里面可以使用 limit()skip()这两个方法来实现,但是更推荐使用数组切割的语法:
        [python] 
         
        1. # Only the first 5 people  
        2. users = User.objects[:5]  
        3.   
        4. # All except for the first 5 people  
        5. users = User.objects[5:]  
        6.   
        7. # 5 users, starting from the 10th user found  
        8. users = User.objects[10:15]  
        你可以指定让查询返回一个结果。如果这个条在数据库中不存在,那么会引发IndexError 。使用first() 方法在数据不存在的时候会返回None:
        [python] 
         
        1. >>> # Make sure there are no users  
        2. >>> User.drop_collection()  
        3. >>> User.objects[0]  
        4. IndexError: list index out of range  
        5. >>> User.objects.first() == None  
        6. True  
        7. >>> User(name='Test User').save()  
        8. >>> User.objects[0] == User.objects.first()  
        9. True  
        查询唯一的结果
        在collection中查询唯一的结果,使用get()方法。如果没有结果匹配会引发 DoesNotExist。如果有多个结果返回的话会引发MultipleObjectsReturned
        有一个变种的方法,get_or_create() 它会新建一个document如果没有结果匹配。里面的参数会作为这个document的默认值:
        [python] 
         
        1. >>> a, created = User.objects.get_or_create(name='User A', defaults={'age': 30})  
        2. >>> b, created = User.objects.get_or_create(name='User A', defaults={'age': 40})  
        3. >>> a.name == b.name and a.age == b.age  
        4. True  
        默认Document查询
        默认情况下,objects属性会将collection的所有结果返回为一个 QuerySet 对象,并且没有进行过滤。这一点可以通过给document定义一个方法来修改QuerySet 。这个方法需要两参数--- doc_cls 和 queryset 。第一个参数是定义这个方法的 Document 类名,第二个参数是初始化的 QuerySet。这个方法需要使用 queryset_manager()来装饰来使它被认可。   
        [python] 
         
        1. class BlogPost(Document):  
        2.     title = StringField()  
        3.     date = DateTimeField()  
        4.  
        5.     @queryset_manager  
        6.     def objects(doc_cls, queryset):  
        7.         # This may actually also be done by defining a default ordering for  
        8.         # the document, but this illustrates the use of manager methods  
        9.         return queryset.order_by('-date')  

        你不用调用objects 方法,你可以定义定制的管理方法:

        [python]
         
        1. class BlogPost(Document):  
        2.     title = StringField()  
        3.     published = BooleanField()  
        4.  
        5.     @queryset_manager  
        6.     def live_posts(doc_cls, queryset):  
        7.         return queryset.filter(published=True)  
        8.   
        9. BlogPost(title='test1', published=False).save()  
        10. BlogPost(title='test2', published=True).save()  
        11. assert len(BlogPost.objects) == 2  
        12. assert len(BlogPost.live_posts()) == 1  

        定制QuerySet

        当你想自己定义一些方法来过滤document的时候,继承 QuerySet类对你来说就是个好的方法。在document里面使用一个自定义的QuerySet类,在document里的meta字典里设置queryset_class的值就可以实现了。

        [python]
         
        1. class AwesomerQuerySet(QuerySet):  
        2.   
        3.     def get_awesome(self):  
        4.         return self.filter(awesome=True)  
        5.   
        6. class Page(Document):  
        7.     meta = {'queryset_class': AwesomerQuerySet}  
        8.   
        9. # To call:  
        10. Page.objects.get_awesome()  
        给结果集计数
        就像限制和跳过结果一样,QuerySet对象提供了用来计数的方法--count(),不过还有一个更加符合python的方法来实现:
        [python]
         
        1. num_users = len(User.objects)  
        更多功能的计数
        当你想为document的特定的字段的数量计数的时候,可以使用sum():
        [python] 
         
        1. yearly_expense = Employee.objects.sum('salary')  
        当你为某个字段求平均值的时候,可以使用average():
        [python] 
         
        1. mean_age = User.objects.average('age')  
        mongoengine提供了一个方法来获取一个在集合里item的频率,item_frequencies(),下面是一个例子: 
        [python] 
         
        1. class Article(Document):  
        2.     tag = ListField(StringField())  
        3.   
        4. # After adding some tagged articles...  
        5. tag_freqs = Article.objects.item_frequencies('tag', normalize=True)  
        6.   
        7. from operator import itemgetter  
        8. top_tags = sorted(tag_freqs.items(), key=itemgetter(1), reverse=True)[:10]  
        检索字段的子集
        有时候你只想检索一条document的某些字段,可以使用only(),把需要检索的字段作为参数,没有选中的字段则会返回默认值:
        [python] 
         
        1. >>> class Film(Document):  
        2. ...     title = StringField()  
        3. ...     year = IntField()  
        4. ...     rating = IntField(default=3)  
        5. ...  
        6. >>> Film(title='The Shawshank Redemption', year=1994, rating=5).save()  
        7. >>> f = Film.objects.only('title').first()  
        8. >>> f.title  
        9. 'The Shawshank Redemption'  
        10. >>> f.year   # None  
        11. >>> f.rating # default value  
        12. 3  
        当你又需要别的字段的时候,使用reload() 方法。
        高级查询

        有时候使用关键字参数返回的QuerySet不能完全满足你的查询需要。例如有时候你需要将约束条件进行与,或的操作。你可以使用mongoengine提供的 Q 类来实现,一个 Q 类代表了一个查询的一部分,里面的参数设置与你查询document的时候相同。建立一个复杂查询的时候,你需要用 & 或 |  操作符将 Q 对象连结起来,例子如下:

        [python] 
         
        1. # Get published posts  
        2. Post.objects(Q(published=True) | Q(publish_date__lte=datetime.now()))  
        3.   
        4. # Get top posts  
        5. Post.objects((Q(featured=True) & Q(hits__gte=1000)) | Q(hits__gte=5000))  
        自动更新

        你而已对一个QuerySet()使用update_one()update()来实现自动更新,有一些可以与这两个方法结合使用的操作符: 

      • set – 设置成一个指定的值
      • unset – 删除一个指定的值
      • inc – 将值加上一个给定的数
      • dec – 将值减去一个给定的数
      • pop – 将 list 里面的最后一项移除
      • push – 在 list 里面添加一个值
      • push_all – 在 list 里面添加好几个值
      • pull – 将一个值从 list 里面移除
      • pull_all – 将好几个值从 list 里面移除
      • add_to_set – 如果list里面没有这个值,则添加这个值自动更新的语法与查询的语法基本相同,区别在于操作符写在字段之前:
        [python] 
         
        1. >>> post = BlogPost(title='Test', page_views=0, tags=['database'])  
        2. >>> post.save()  
        3. >>> BlogPost.objects(id=post.id).update_one(inc__page_views=1)  
        4. >>> post.reload()  # the document has been changed, so we need to reload it  
        5. >>> post.page_views  
        6. 1  
        7. >>> BlogPost.objects(id=post.id).update_one(set__title='Example Post')  
        8. >>> post.reload()  
        9. >>> post.title  
        10. 'Example Post'  
        11. >>> BlogPost.objects(id=post.id).update_one(push__tags='nosql')  
        12. >>> post.reload()  
        13. >>> post.tags  
        14. ['database', 'nosql']  
  • 相关阅读:
    读取INI配置文件
    在VB编程中,若一行代码太长需要换行时,行尾要加什么符号
    使用order by和group by的分析
    转 Sqlserver_left join 、right join、 inner join 用法
    Python 字典(Dictionary)操作详解
    转sql server新增、修改字段语句(整理)
    Winform TextBox中只能输入数字的几种常用方法(C#)
    数据库的范式,第一、二、三、四、五范式、BC范式
    【操作系统】银行家算法
    转 图解排序算法(三)之堆排序
  • 原文地址:https://www.cnblogs.com/fillim/p/4864528.html
Copyright © 2011-2022 走看看