转自:MongoEngine 查询(翻译)
数据库查询
Document 对象有一个 objects 属性,用来访问在数据库中跟这个类有关的对象。这个 objects 属性其实是一个QuerySetManager ,它会创建和返回一个新的 QuerySet 对象的访问。这个 QuerySet 对象可以从数据库中遍历获取的文档:
过滤查询
可以通过调用 QuerySet 对象的关键字参数来对数据查询进行过滤,关键字查询中的键和你想要查询的Document 中的字段一致:
对于内嵌document的字段可以使用 __ 来代替对象属性访问语法中的 . 进行访问:
查询操作符
在查询中也可以使用操作符,只要将其加在关键字的双下划线之后即可:
可用的运算符如下:
字符串查询
以下操作符可以快捷的进行正则查询:
-
exact – 字符串型字段完全匹配这个值
-
iexact – 字符串型字段完全匹配这个值(大小写敏感)
-
contains – 字符串字段包含这个值
-
icontains – 字符串字段包含这个值(大小写敏感)
-
startswith – 字符串字段由这个值开头
-
istartswith – 字符串字段由这个值开头(大小写敏感)
-
endswith – 字符串字段由这个值结尾
-
iendswith – 字符串字段由这个值结尾(大小写敏感)
-
match – 执行 $elemMatch 操作,所以你可以使用一个数组中的 document 实例
地理查询
PASS
列表查询
对于大多数字段,这种语法会查询出那些字段与给出的值相匹配的document,但是当一个字段引用 ListField 的时候,而只会提供一条数据,那么包含这条数据的就会被匹配上:
class Page(Document):
tags = ListField(StringField())
原始查询
你可以通过 __raw__ 参数来使用一个原始的 PyMongo 语句来进行查询,这样可以进行原始的完整查询:
Page.objects(__raw__={'tags': 'coding'})
限制和跳过结果
就像传统的ORM一样,你有时候需要限制返回的结果的数量,或者需要跳过一定数量的结果。QuerySet 里面可以使用 limit() 和 skip() 这两个方法来实现,但是更推荐使用数组切割的语法:
你可以指定让查询返回一个结果。如果这个条在数据库中不存在,那么会引发 IndexError 错误 。使用 first() 方法在数据不存在的时候会返回 None:
>>>
默认Document 查询
默认情况下,Document的objects 属性返回一个一个 QuerySet 对象,它并没有进行任何筛选和过滤,它返回的是所有的数据对象。这一点可以通过给一个 document 定义一个方法来修改 一个queryset 。这个方法需要两参数__doc_cls 和 queryset 。第一个参数是定义这个方法的 Document 类名(从这个意义上来说,这个方法像是一个 classmethod() 而不是一般的方法),第二个参数是初始化的 queryset。这个方法需要使用 queryset_manager()来装饰来它,使得它被认可。
class BlogPost(Document):
title = StringField()
date = DateTimeField()
@queryset_manager
def objects(doc_cls, queryset):
你不用调用 objects 方法,你可以自定义更多的管理方法,例如:
class BlogPost(Document):
title = StringField()
published = BooleanField()
@queryset_manager
def live_posts(doc_cls, queryset):
return queryset.filter(published=True)
BlogPost(title='test1', published=False).save()
BlogPost(title='test2', published=True).save()
assert len(BlogPost.objects) == 2
assert len(BlogPost.live_posts()) == 1
自定义 QuerySets
当你想自己定义一些方法来过滤 document 的时候,继承 QuerySet 类对你来说就是个好的方法。为了在 document 里面使用一个自定义的 QuerySet 类,你可以在 document 里的 meta 字典里设置 queryset_class 的值来实现它。
class AwesomerQuerySet(QuerySet):
def get_awesome(self):
return self.filter(awesome=True)
class Page(Document):
meta = {'queryset_class': AwesomerQuerySet}
Aggregation 聚合
MongoDB 提供了开箱即用的聚合方法,但没有 RDBMS 提供的那样多。MongoEngine 提供了一个包装过的内置的方法,同时自身提供了一些方法,它实现了在数据库服务上执行的 Javascript 代码的功能。
结果计数
就像限制和跳过结果一样, QuerySet 对象提供了用来计数的方法 - count(),不过还有一个更 Pythonic 的方法来实现:
num_users = len(User.objects)
更多功能
当你想为 document 的特定的字段的数量计数的时候,可以使用 sum():
yearly_expense = Employee.objects.sum('salary')
当你想求某个字段的平均值的时候,可以使用 average():
mean_age = User.objects.average('age')
MongoEngine 提供了一个方法来获取一个在集合里 item 的频率 - item_frequencies()。下面一个例子可以生成 tag-clouds:
class Article(Document):
tag = ListField(StringField())
查询效率和性能
PASS
高级查询
有时候使用关键字参数返回的 QuerySet 不能完全满足你的查询需要。例如有时候你需要将约束条件进行and,or 的操作。你可以使用 MongoEngine 提供的 Q 类来实现,一个 Q 类代表了一个查询的一部分,里面的参数设置与你查询document 的时候相同。建立一个复杂查询的时候,你需要用 & 或 | 操作符将 Q 对象连结起来。例如:
from mongoengine.queryset.visitor import Q
Atomic updates(原子更新)
MongoDB 文档 可以通过QuerySet 上的 update_one()、update()、modify() 方法自动更新。下面几种操作符可以被用到这几种方法上:
原子更新的语法类似于查询语法,区别在于修饰操作符位于字段之前,而不是之后:
>>> post = BlogPost(title='Test', page_views=0, tags=['database'])
>>> post.save()
>>> BlogPost.objects(id=post.id).update_one(inc__page_views=1)
>>> post.reload()
如果没有修饰操作符,则默认为$set:
BlogPost.objects(id=post.id).update(title='Example Post')
BlogPost.objects(id=post.id).update(set__title='Example Post')
服务器端 JavaScript 执行
可以写 Javascript函数,然后发送到服务器来执行。它返回结果是 Javascript 函数的返回值。这个功能是通过QuerySet()对象的exec_js() 方法实现。传递一个包含一个Javascript函数的字符串作为第一个参数。
其余位置的参数的名字字段将作为您的Javascript函数的参数传递过去。
在 JavaScript 函数范围中,一些变量可用:
def sum_field(document, field_name, include_negatives=True):
code = """
function(sumField) {
var total = 0.0;
db[collection].find(query).forEach(function(doc) {
var val = doc[sumField];
if (val >= 0.0 || options.includeNegatives) {
total += val;
}
});
return total;
}
"""
options = {'includeNegatives': include_negatives}
return document.objects.exec_js(code, field_name, **options)
来源:https://www.cnblogs.com/hailin2018/p/15080288.html |