以sqlalchemy为后端的json查询引擎
mongosql的Python项目详细描述
MongoSQL
mongosql是一个json查询引擎,允许您查询sqlalchemy 就像MongoDB数据库一样。
主要用例是与ui的交互: 每次用户界面需要排序、过滤、分页或加载 相关对象,无需编写一行重复代码!
它将允许api用户发送json查询对象和rest请求, 它将控制生成结果集的方式:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))
厌倦了为分页、筛选、排序添加查询参数? 这是最终的解决方案。
注意:目前,仅使用PostgreSQL进行测试。
目录
- 查询
- MongoSQL编程接口
- MongoQuery
- 创建Mongoquery
- 可重复使用
- 查询:mongoquery.query()
- 获取结果:mongoquery.end()
- 获取各种结果
- MongoQuery配置
- MongoQueryAPI
- MongoQuery(模型,handler_settings=none)
- mongoquery.from_query(query)->;mongoquery
- MongoQuery.With懔Session(SSN)->;MongoQuery
- MongoQuery.query(**查询对象)->;MongoQuery
- mongoquery.end()->;查询
- MongoQuery.end_count()->;计数查询
- MongoQuery.result嫒u contains嫒entities()->;bool
- MongoQueryResult是MongoQuery。结果_是_scalar()->;bool
- MongoQuery.result_是元组()->;bool
- Mongoquery.get_final_query_object()->;dict
- MongoQuery.确保"已加载"(*cols)->;MongoQuery
- MongoQuery.get_Projection_Tree()->;dict
- mongoquery.get_full_projection_tree()->;dict
- MongoQuery.puck戋Instance(Instance)->;dict
- 处理程序
- MongoQuery
- CRUD帮助程序
- 其他有用的工具
查询
如果您知道如何在mongodb中查询文档,那么可以使用相同的语言查询数据库。 MongoSQL使用熟悉的MongoDB查询运算符 语言和一些自定义添加。
使用json格式的query对象,您可以进行排序、筛选、分页和其他操作。 您通常会在url查询字符串中发送此对象,如下所示:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
但是,参数的名称可能因项目而异。
查询对象语法
查询对象是一个json对象,api用户可以提交给服务器以更改生成结果的方式。 它是具有以下属性的对象:
项目
项目操作选择要加载的字段排序
:排序操作决定结果的排序筛选
:筛选操作使用您的条件筛选结果连接
:连接操作加载相关模型joinf
:筛选联接操作加载带有筛选的相关模型聚合
:聚合操作允许计算统计信息组
:组操作确定如何在进行聚合时对行进行分组跳过
,限制
:对行进行切片:对结果进行分页计数
:对行进行计数对行数进行计数而不产生结果
一个示例查询对象是:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
相关章节提供了每个操作的详细语法。
请记住,虽然mongosql提供了一种足够丰富的查询语言来完成大多数典型的任务, 在某些情况下,自定义api的实现会更好,甚至是唯一可用的选项。
MongoSQL不是设计为o是sql的完全替代品;它的设计只是为了防止您 重复性工作:)因此,在MongoSQL中,您可能想到的一些查询是不可能实现的,这是非常好的。
操作
项目运营
投影对应于SQL查询的选择部分。
在MongoDB术语中,投影是从文档中选择字段子集的过程。
您的模型有许多字段,但并不总是需要全部字段。通常,你所需要的只是一小部分 他们当中。当您使用此操作时,会为您投影一些字段。
通过projéct
操作,您可以列出希望在从api端点获取的数据中包含的字段。
为此,可以列出所需的字段(称为include mode),也可以列出
不需要(称为排除模式)。
在后端生成的数据查询将只获取您请求的字段,可能会节省很多 带宽。
投影的示例如下:
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
语法
项目操作支持以下语法:
数组语法。
提供要包含的字段名数组。 其余的将被排除在外。
示例:
{project:['login','first_name']}
对象语法。
提供映射到a
1
(include)或a0
(exclude)的字段名对象。示例:
{'a':1,'b':1}#Includespecificfields.Allotherfieldsareexcluded{'a':0,'b':0}#Excludespecificfields.Allotherfieldsareincluded
注意,不能将两者混合使用:要么使用all
1
s指定要包含的字段, 或者使用all0
s指定要排除的字段。注意:一种特殊情况是所谓的"完全投影":当投影对象提到每个属性时 对于一个模型,您可以将
1
s设置为某些,并将0
s设置为同一对象中的其他。明智使用。
默认情况下排除的字段
请注意,默认情况下,模型中存在的某些字段可能不包括在中:这是
后端开发人员可能在服务器上配置了默认排除设置。
除非明确要求,否则将不会接收这些字段。 这可能适用于包含大量数据或需要进行一些计算的某些字段。
要包含这些字段,必须显式地请求它们:只需使用它们的名称 在您请求的字段列表中。
相关型号
通常,为了加载相关模型(例如,用户的用户配置文件
,或与此模型相关的一些其他数据)。
您可以使用连接操作。
不过,为了方便起见,现在还可以通过在投影中指定相关模型的名称来加载它们, 好像是一片田野。例如:
{project:{id:1,name:1,user_articles:1// the related model will be loaded}}
此请求将为您加载相关的用户文章。
请注意,出于安全原因,某些关系将被禁用。
排序操作
排序对应于SQL查询的排序方式
部分。
用户界面通常要求记录按某个或多个字段排序。
排序操作允许api用户指定结果的排序, 这对于返回项列表的api端点来说是有意义的。
排序操作的示例如下:
$.get('/api/user?query='+JSON.stringify({// sort by age, descending;// then sort by first name, alphabeticallysort:['age-','first_name+'],}))
语法
数组语法。
列名列表,可选地以排序方向作为后缀:
-
表示desc
,+
表示asc
。 默认值为+
示例:
['a+','b-','c']// -> a ASC, b DESC, c DESC
不支持对象语法,因为它不保留键的顺序。
过滤器操作
过滤对应于SQL查询中的部分。
MongoSQL支持的API端点s通常返回all项的列表,并将其保留为 API用户根据自己的喜好对其进行筛选。
过滤示例:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))0
字段运算符
以下是MongoDB查询运算符 支持运算符:
支持以下MongoDB运算符:
{a:1}
-相等检查:字段=值
。这是$eq
运算符的快捷方式。{a:{$eq:1}
-相等检查:字段=值
(别名)。{a:{$lt:1}
-小于:字段<;值
{a:{$lte:1}
-小于或等于:字段<;=值
{a:{$ne:1}
-不等式检查:字段!=值
{a:{$gte:1}
-大于或等于:字段>;=值
{a:{$gt:1}
-大于:字段>;值
{a:{$prefix:1}
-前缀:类似"value%"的字段
{a:{$in:[…]}
-任何一个。字段等于任何给定的值数组。{a:{$nin:[…]}
-没有。字段不等于任何给定的值数组。{a:{$exists:true}
-值不是null
对于标量值,在数组
字段上支持以下运算符:
{arr:1}
-包含检查:字段数组包含给定值:任意(数组)=值
{arr:{$ne:1}
-非包含检查:字段数组不包含值:all(数组列)!=值
{arr:{$size:0}
-长度为n(零,用于检查空数组)
对于数组值,在数组
字段上支持以下运算符:
{arr:[…]}
-相等检查:两个数组完全相等:arr=value
{arr:{$ne:[…]}
-不等式检查:两个数组不相等:arr!=值
{arr:{$in:[…]}
-交集检查。检查两个数组是否有公共元素。{arr:{$nin:[…]}
-没有交叉检查。检查两个数组是否没有公共元素。{arr:{$all:[…]}
-包含给定数组中的所有值
布尔运算符
除了将字段与值进行比较之外,还支持以下布尔运算符 使您能够进行复杂的查询:
{$或:[{..criteria..},…]}
-any为true{$和:[{..criteria..},…]}
-都是真的{$nor:[{..criteria..},…]}
-无为真{$不:{..条件..}}
-否定
示例用法:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))1
相关列
您还可以通过相关模型上的列筛选数据。 这可以通过在关系名称后使用点来实现:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))2
加入操作
连接对应于sql查询的左连接
部分(尽管作为单独的查询实现)。
在后端数据库中,数据通常以规范化的形式保存: 不同种类的物品存放在不同的地方。 这意味着,无论何时您需要相关的项目,您都必须明确请求它。
join操作允许您加载这些相关项。
请记住,由于安全问题,大多数关系都将在后端被禁用 暴露敏感数据。因此,每当前端开发人员需要加载关系时, 必须在后端手动启用!请随意询问。
实例跟随.
语法
数组语法。
在最简单的形式中,您只需提供关系的名称列表 想要加载:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))
3对象语法。
这种语法提供了极大的灵活性:对于嵌套查询对象,现在可以应用操作 到相关实体:只选择几个字段(投影),排序,过滤,甚至限制它!
嵌套查询对象支持投影、排序、筛选,甚至连接其他关系,以及 限制加载的相关实体的数量!
在这个对象语法中,对象是一个嵌入的查询对象。例如:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))
4请注意,
null
可用于加载关系,而无需自定义查询。
过滤连接操作
联接操作具有以下行为:
当您请求加载关系时,如果找不到任何项,则返回空值
(anull
或空数组)。
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))5
这个joinf
过滤连接操作的作用与join
的作用相同;
但是,如果没有相关项,则主项也会被删除。
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))6
这个特性,老实说,很奇怪,而且只能用于向后兼容一个已经存在的bug 在一些早期的mongosql版本中。它在某些情况下被证明是有用的,所以这个bug被命名为 放置在MongoSQL库中:)
注意,joinf``不支持
skip和
限制`
在嵌套实体上,因为它是用postgres实现的。
聚合操作
聚合对应于具有聚合函数的SQL查询的选择…
部分。
有时api用户不需要数据本身,而是需要一些关于数据的统计信息:最小值, 最大值,平均值,所有值的总和。
聚合就是这样做的:让api用户对数据执行统计查询。 它的功能是有限的,但本着mongosql的精神,它将为后端开发人员节省一些日常工作。
示例:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))7
请注意,出于安全原因,必须为后端的每个字段手动启用聚合。
语法
语法是一个对象,它声明用于保存结果的自定义字段名:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))8
表达式可以是:
列名:本质上,将一列投影到结果集中,以便可以获得原始值
示例:
$.get('/api/user?query='+JSON.stringify({sort:['first_name-'],// sort by `first_name` DESCfilter:{age:{$gte:18}},// filter: age >= 18join:['user_profile'],// load related `user_profile`limit:10,// limit to 10 rows}))
9这仅在与组操作结合使用时才有用。 默认情况下,在后端禁用它。
聚合函数:
{$min:operand}
-最小值{$max:operand}
-最大值{$avg:operand}
-平均值{$sum:operand}
-值的和
操作数可以是:
列名:将聚合函数应用于列
示例:
0GET /api/user?query={"filter":{"age":{"$gte":18}}}
布尔表达式:请参见过滤操作。
这是一个非常有用的技巧。 因为布尔表达式的结果是
1
当它为真时,可以取它们的$sum
, 并计算与该条件匹配的行数。示例:
1GET /api/user?query={"filter":{"age":{"$gte":18}}}
整数值(仅由
$sum
运算符支持)示例:
2GET /api/user?query={"filter":{"age":{"$gte":18}}}
请注意,聚合通常只有在与组操作一起使用时才有意义
组操作
分组对应于SQL查询的分组依据
部分。
默认情况下,聚合操作在所有行上都有统计结果。
例如,如果您要求{avg-age:{$avg:'age'}
,您将得到所有用户的平均年龄。
通常这是不够的,你会希望统计计算的项目组。 这就是组操作的作用:指定要用作"组"指示器的字段。
最好从几个例子开始。
示例1:计算每个特定年龄段的用户数。
我们使用age
字段作为组鉴别器,因此计算每个组的用户总数。
结果是:类似于:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
3
代码:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
4
示例2:计算每个职业的平均工资
GET /api/user?query={"filter":{"age":{"$gte":18}}}
5
语法
GET /api/user?query={"filter":{"age":{"$gte":18}}}
如您所见,group运算符接收列名数组。
切片操作
切片对应于限制。偏移量..
SQL查询的一部分。
切片操作由两个可选部分组成:
limit
将限制api返回的项目数跳过
会将"窗口"移动许多项
这两个元素一起实现分页。
示例:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
6
值:可以是数字,也可以是anull
计数操作
切片对应于SQL查询的选择计数(*)
部分。
简单地说,返回项目的数量,而不返回项目本身。只是一个数字。就这样。
示例:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
7
1
是开关。将其替换为0
以停止计数。
注意:在MongoSQL 2.0中,有一种方法可以同时获取项列表和它们的计数。 这将比两个单独的查询有更好的性能。 请查看:countingquery和mongoquery.end count()。
json列支持
json
(或jsonb
)字段是包含嵌入对象的列,
它本身也有田地。您可以使用点访问这些字段。
给定模型字段:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
8
您可以引用json字段的内部:
GET /api/user?query={"filter":{"age":{"$gte":18}}}
9
支持它的操作:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
0过滤操作:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
1或者这就是测试属性是否丢失的方法:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
2注意:postgresql对于数据类型有点反复无常,因此mongosql试图使用您提供的操作数来猜测它。 因此,当使用已知包含
float
类型字段的属性进行筛选时,请提供float
值!聚合:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
3
MongoSQL编程接口
蒙哥马利
创建MongoQuery
mongoquery
是一个主要工具,它允许您对sqlalchemy处理的数据库执行json查询对象。
有两种使用方法:
手动构造MongoQuery,为其提供模型:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
4为您的基地使用便利混音:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
5使用这个基础,您的模型将有一个快捷方法,该方法返回一个
mongoquery
:{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
6使用
mongoquery()
可以从会话构造查询:{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
7或者从sqlalchemy.orm.query, 它允许您应用一些初始筛选:
{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
8
可重复使用
amongoquery
反对它self不可重用:它只能进行一次查询。
但是,保存一些初始化并为新请求做好准备是有意义的。
出于性能原因,这必须使用 包装对象具有 一旦准备好MongoQuery,就可以给它一个QueryObject: 因为 让我们记住,mongoquery生成的查询可以返回三种结果: 使用方法如下: 很可能,您根本不需要处理这个问题:只需使用crud helpers
为您实现大部分逻辑。 这些设置可以很好地保存在amongoquerysettingsdict中
作为第二个参数给Mongoquery。 示例: 可用的设置为: 注意:如果希望api默认返回所有字段,请使用 (用于:项目)
granular 这是一种性能保护:当api用户不需要某些列时,
它们没有装载。但是,当应用程序试图访问它们时。
当raiseload_col=true时,需要手动加载所有列和关系
(使用 这是为了在开发人员可能仍然引用
到不再存在的旧列。 当关系或列从模型中消失时,建议
向后兼容的方法是使两者都小于code>传统字段可重用的包装器手动完成
和{project:['id','name'],#Onlyfetchthesecolumnssort:['age+'],#Sortbyage,ascendingfilter:{#Filterconditionsex:'female',#Girlsage:{$gte:18},#Age>=18},join:['user_profile'],#Loadthe'user_profile'relationshiplimit:100,#Display100perpageskip:10,#Skipfirst10rows}
9
mongoquery
的所有方法,但在使用时会生成正确的副本。
把它当作一个工厂。查询:
mongoquery.query()
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
0
正在获取结果:
mongoquery.end()
mongoquery
只是sqlalchemy的query
的包装,所以可以得到query
并从中获取结果:$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
1
得到各种结果
{count:1}
mongoquery
有三种方法可以帮助您检测得到的信息:mongoquery.result_包含实体()
mongoquery.result_是_scalar()
mongoquery.result_是元组()
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
2
MongoQuery配置
mongoquery
有很多设置,可以让您配置查询的方式,
微调它们的安全限制,并实现一些自定义行为。$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
3
默认投影
:(用于:项目)
未提供输入时使用的默认投影。
当给定一个输入值时,default_projection
根本不使用:它覆盖默认值
完全。如果要将某些默认值合并到每个投影中,请使用以下某些设置:
默认排除
,强制排除
,强制排除
none
。如果你想让api
默认情况下,使用空列表。
这是因为none
被视为"无默认",而mongosql使用其内部默认值包括
所有字段;但[]
被视为"默认不包含字段"的指令。默认排除(for:project)
从每个投影中排除的属性列表。
加载这些属性的唯一方法是显式地请求它们。
对于包含大量数据或需要额外查询的属性,请使用此选项。
默认排除属性
:(用于:项目)
当true
时,所有@属性
和@混合属性
属性
默认情况下将被排除(放入default_exclude
)。
这是一条方便的捷径。
使用默认包含属性
否决。默认未包含属性
:(用于:项目)
不排除的@property
和@hybrid\u property
属性列表:
它们将被视为其他列。捆绑项目
:(用于:项目)
声明依赖于正在加载的其他列的列的dict。
当您有一个依赖于某些列的属性,并且用户希望加载它时,setti天然气
已将属性的名称映射到依赖列的列表。
示例:{'全名':['名字','姓氏']}强制包含(for:project)
始终加载并包含在输出中的属性列表。
强制排除(for:project)
始终从输出中卸载和排除的属性列表。
无论您做什么,都无法访问它们。
确保已加载(for:project)
即使用户没有请求也将加载的列的列表。
但是,这些列将安静地加载,而不包括在投影中。
用例:代码所需的列。如果没有它们,它会崩溃,以防用户排除它们。
您不希望强制包含它们,但希望"悄悄"包含它们。
raiseload
:仅当延迟加载列时才升高raiseload_rel(用于:连接)
granular
raiseload
:仅当延迟加载关系时才升高raiseload
:(用于:项目,联接)
当未加载列或关系时引发异常
由应用程序访问。
这将导致额外的SQL查询,查询速度非常慢。undefer()
和joinedload()
)或使用mongoquery.ensure_loaded()
聚合列
:(用于:聚合)
启用聚合的列名列表。
未显式启用聚合的所有列都将被禁用。聚合标签
:(用于:聚合)
是否启用标记列(别名)。
这些功能基本上是无用的,
但在这里存在是为了完成与MongoDB查询的兼容性。强制过滤器
:(用于:过滤器)
一本字典,它有一个过滤器,每个请求都会被强制执行;
或者返回query.filter()过滤条件的python可调用(模型)
。标量运算符
:(for:filter)
标量列的附加运算符的指令。
声明全局运算符的更好方法是将mongofilter子类
并声明类中的其他运算符。数组运算符(for:filter)
数组列的附加运算符的dict。
允许的关联
:(for:join)
用户可以加载的关系的显式列表。
当尝试"加入"时,所有其他关系都将引发DisablederRor。禁止的关系(for:join)
将引发用户无法加载的关系列表:disablederror。
最大项目数
:(用于:限制)
此查询可以加载的最大项数。
用户永远不能超过这个值,这个值会被强制加载到每个查询中。旧字段
:(用于:所有内容)
以前存在但不再存在的字段(列、关系)列表。
所有的处理者都会悄悄地忽略这些领域。请注意,它们仍将出现在投影中
从project
和join
处理程序。如果你依赖它们,你的代码将不得不忽略
这些字段也是。强制包含
,
以及一个@property,它为兼容性提供了一些假值。
这样,即使客户再也不能手动加入,他们也总能得到一些东西。
聚合已启用
:启用/禁用聚合
处理程序
已启用计数
:启用/禁用计数处理程序
过滤器已启用
:启用/禁用过滤器
处理程序
组已启用
:启用/禁用组
处理程序
连接已启用
:启用/禁用连接
处理程序
joinf_enabled
:启用/禁用joinf
处理程序
限制已启用
:启用/禁用限制
处理程序
项目已启用
:启用/禁用项目
处理程序
已启用排序
:启用/禁用排序
处理程序
相关
:基于关系名称的相关模型查询设置。
例如,当用户
具有名为"articles"的关系时,
您可以将"项目"键放入此设置中,并配置
如何查询相关模型。
这样,当模型是 通过另一个模型的关系查询。
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))4
相关模型
:配置每个关系时似乎太多,您只需要定义
每个型号的通用设置,请使用此设置而不是"相关"。
它将根据目标模型自动配置每个关系。
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))5
如果在 "相关"设置。
"related_models"设置实际上允许您拥有一个全局指令 定义应用于实体的"默认"规则,无论实体如何加载: 直接或通过另一个模型的关系。
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))6
不过,要小心:如果每个模型都继承其允许的关系, 通过一系列嵌套连接几乎可以获得任何对象!
更多设置可通过crud助手设置获得, 它是MongoQuery配置的扩展
可写属性
:是否可写模型属性?当
false
时,传入的json对象将只允许设置/修改real 柱。保存@属性值的唯一方法是使用
@保存关系
decorator并手动处理该值。当
true
时,即使是@property
和@hybrid\u property
对象也可以写入。 请注意,与其他字段一样,验证取决于您。 为了完全可写,它还必须位于rw廑字段的列表中。
只读字段列表。
这些字段只能在代码中修改。 当这些字段中的任何一个被提交到api端点时,它都会被忽略, 甚至从传入的实体dict中删除。
rw\u字段
:可写字段的列表。当您有太多的
ro_字段时,可能更容易提供 那些是可写的;其余的都变成只读的。
常量字段
:常量字段列表。这些字段只能在创建对象时设置,但不能更改 当它被修改时。
查询默认值
:每个查询对象的默认值。这是为每个查询提供默认值的默认查询对象。 例如,这个m可以是默认的
限制:100
,也可以是默认的项目
运算符。**MongoQuery设置
:有关MongoQuery的更多设置
(如上所述)
Mongoquery API
MongoQuery(型号,处理程序设置=无)
mongoquery是sqlalchemy的查询的包装器,它可以安全地执行json查询对象
mongoquery.from_query(query)->;mongoquery
指定要使用的自定义sqlalchemy查询。
比如说,它可能已经应用了初始过滤。 如果未提供默认查询,则使用默认查询。
参数:
查询:查询
:要使用的初始sqlalchemy查询(例如,预应用初始筛选器)
返回mongoquery
mongoquery.with_session(ssn)->;mongoquery
使用给定的sqlalchemy会话进行查询
参数:
ssn:session
:用于查询的sqlalchemy会话
。
返回mongoquery
mongoquery.query(**查询对象)->;mongoquery
从对象生成MongoSQL查询
参数:
**查询对象
:要执行的查询对象。
返回mongoquery
例外情况:
无效的relationerror
:输入中提供的关系名称无效无效列错误
:输入中提供的列名无效invalidqueryerror
:任何查询对象节的语法错误invalidQueryRor
:提供了未知的查询对象操作(额外的键)
mongoquery.end()->;查询
获取生成的sqlalchemy查询
对象
返回查询
mongoquery.end_count()->;计数查询
获取结果,并计算总行数。
意识到成本将大大高于没有总数的情况, 但仍然比两个单独的查询便宜。
数字:这将使小结果集提高约50%,使大结果集提高约15%。
如需有关详细信息,请参阅countingquery。
返回countingquery
示例:
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))7
mongoquery.result_包含_entities()->;bool
测试结果是否包含实体。
这通常是在没有"聚合"、"组"和"计数"查询的情况下发生的。
返回bool
mongoquery.result_是_scalar()->;bool
测试结果是否是标量值,如count
在这种情况下,您将按如下方式获取它:
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))8
返回bool
mongoquery.result_是元组()->;bool
测试结果是否为键控元组列表,如"分组依据"
在这种情况下,您可以这样取:
$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))9
返回bool
mongoquery.确保加载了(*cols)->;mongoquery
确保已加载给定的列、关系和相关列
尽管用户可能正在进行任何投影和连接,但请确保已加载给定的cols
。
这将确保加载每一列,连接每一个关系,并且不包含这些关系
进入投影
和提取实例
应用程序代码将使用此方法处理以下情况:
- api用户只请求加载字段"a"、"b"、"c"
- 应用程序代码的操作需要字段"d"
- 用户不希望在输出中看到"d"。 解决方案:使用确保加载了'd',然后获取'u instance()
限制:
- 如果用户已请求对关系进行筛选,则不能对其使用"确保已加载"()。 此方法将引发invalidQueryRor()。 这是有道理的,因为如果应用程序代码依赖于某种关系的存在, 它当然需要完全加载和未过滤。
- 如果请求不包含任何实体(例如使用"group"或"aggregate"处理程序), 此方法将抛出断言错误
如果您只需要知道是否加载了某些内容,请使用MongoQuery。contains()代替。
记住,每次对关系使用secure_loaded()时,都会禁用对其进行筛选的可能性!
参数:
*cols
:列名('age')、关系名('articles')或相关列名('articles.name')
返回mongoquery
例外情况:
valueerror
:给定的列或关系名称无效。 它不会抛出invalidcolumnerror,因为这可能是您的错误,而不是api用户的错误:)invalidQueryRor
:无法合并,因为关系上有筛选器
mongoquery.get_final_query_object()->;dict
获取最终的查询对象dict(在所有处理程序应用默认值之后)。
这个查询对象将包含每个处理程序的名称,包括那些没有输入的处理程序。
返回dict
mongoquery.get_projection_tree()->;dict
得到一个像dict这样的投影,将每个包含的列映射到1, 以及与嵌套投影dict的每个关系。
返回dict
:投影
示例:
{project:['login','first_name']}0
这主要用于调试嵌套查询对象。
mongoquery.get_full_projection_tree()->;dict
获取一个完整的投影树,其中提到每一列,但只包含那些已加载的关系
返回dict
mongoquery.cluck_instance(instance)->;dict
提取一个sqlalchemy实例并使其成为dict
此方法应用于为json编码准备对象。 这确保只包含用户显式请求的属性 结果,而不是代码可能加载的属性。
考虑投影和连接属性。
参数:
实例:对象
:对象
返回dict
处理程序
除此之外,mongoquery
还允许您检查mongoquery的内部。
每个处理程序都可用作MongoQuery的属性
mongoquery.handler嫒project
:处理程序.mongoprojectmongoquery.handler\u sort
:处理程序.mongosortmongoquery.handler嫒group
:处理程序.mongogroupmongoquery.handler嫒join
:处理程序.mongojoinmongoquery.handler\u joinf
:处理程序.mongofilteringjoinmongoquery.handler嫒filter
:处理程序.mongofiltermongoquery.handler_aggregate
:处理程序.mongoaggregatemongoquery.handler嫒limit
:处理程序.mongolimitmongoquery.handler\u count
:处理程序.mongocount
有些人有办法可能对你正在构建的应用程序有用,
尤其是当您需要从mongoquery
中获取一些信息时。
CRUD助手
mongosql旨在帮助api选择数据。 为了减轻为所有模型实现crud的痛苦, mongosql附带了一个crud助手,它向api用户公开了mongosql的查询功能。 与restfulview一起使用 从烧瓶jsontools, CRUD控制器非常容易构建。
crudhelper(model,writable_properties=true,**handler_settings)
crud helper:帮助为api端点实现crud操作的对象:
- 创建:从提交的实体dict构造sqlalchemy实例
- 阅读:使用MongoQuery查询
- 更新:使用dict从提交的实体更新sqlalchemy实例
- 删除:使用MongoQuery进行删除
来源:mongosql/crud/crudhelper.py rel="nofollow">mongosql/crud/crudhelper.py
这个对象应该只初始化一次; 不要对每个查询都这么做,保持在类级别!
很有可能,您会希望将其保持在视图的类级别:
{project:['login','first_name']}1
注意,在"create"和"update"操作期间,这个类允许您编写值
到列属性,以及可写的@property(有setter)。
如果此行为(具有可写属性)不受欢迎,
设置可写属性=false
可用的方法如下:
crudhelper.query_model(query_obj=none,from_query=none)->;mongoquery
使用提供的查询对象生成MongoQuery
请注意,您必须自己提供Mongoquery。 这是因为它必须正确配置handler_设置。
参数:
查询对象:union[mapping,nonetype]=none
:要使用的查询对象
初始化MongoQuery的可选查询from_query:union[sqlalchemy.orm.query.query,nonetype]=none
:用
返回mongoquery
例外情况:
exc.disablederror
:功能被禁用;可能是由于配置问题。请参阅处理程序设置。exc.invalidqueryerror
:用户在查询对象中所做的操作有错误exc.invalidrelationerror
:用户在查询对象中指定的关系名称无效exc.invalidcolumnerror
:用户在查询对象中指定的列名无效
crudhelper.create_model(entity_dict)->;对象
从实体dict创建实例。
此方法允许您设置列和可写属性的值, 但不是关系。使用@saves_relations处理其他字段。
参数:
实体dict:mapping
:实体dict
返回对象
:已创建实例
例外情况:
无效列错误
:无效列无效查询错误
:验证错误
crudhelper.update_model(实体dict,实例)->;对象
通过合并字段从实体dict更新实例
- 属性被复制到
- json指令被浅合并
请注意,因为属性是通过复制的, 此操作不会替换实体;它只是更新实体。
换句话说,此方法执行部分更新: 只更新客户端提供的字段,其余字段保持不变。
参数:
实体dict:mapping
:实体dict实例:对象
:要更新的实例
返回对象
:新实例,已更新
例外情况:
无效列错误
:无效列无效查询错误
:验证错误
严格帮助
严格的crud帮助程序对api用户施加默认值和限制:
来源:mongosql/crud/crudhelper.py rel="nofollow">mongosql/crud/crudhelper.py
- 不能设置只读字段:不使用create,也不使用update
- 常量字段可以最初设置,但永远不会更新
- 查询对象的默认值为每个查询提供默认值,除非重写
实现了以下行为:
- 默认情况下,所有字段都是可写的
- 如果提供了ro_字段,则这些字段变为只读,所有其他字段都是可写的
- 如果提供了rw_字段,则只有这些字段是可写的,所有其他字段都是只读的
- 如果const_字段,则被视为对rw_字段的进一步限制:这些字段将是可写的, 但只有一次。
strictcrudhelper(model,writable_properties=true,ro_fields=none,rw_fields=none,const_fields=none,query_defaults=none,**handler_settings)
初始化一个严格的crud助手
注意:使用**strictcrudhelpersettingsdict()
帮助您处理参数名及其文档!
参数:
模型:declarativemeta
:要使用的模型可写属性:bool=true
:ro-u字段:union[iterable[str],callable,nonetype]=none
:只读属性名列表,或提供列表的callablerw\u字段:union[iterable[str],callable,nonetype]=none
:可写属性名列表,或提供列表的callable常量字段:union[iterable[str],callable,nonetype]=none
:一次设置为常量的属性名列表,或给出列表的可调用属性名列表查询默认值:union[iterable[str],callable,nonetype]=none
:每个查询对象的默认值:查询对象将合并到其中。**处理程序设置
:用于进行查询的mongoquery的设置
示例:
{project:['login','first_name']}2
crudviewmixin()
用于实现crud视图的mixin类。
这个类应该为每个请求重新初始化。
要实现crud视图:
- 实现从请求中提取查询对象的方法
- 在类级别设置crudhelper,用正确的设置初始化它
- 实现
_get_db_session()
和_get_query_object()
方法 - 如有必要,执行
\u save_hook()
以自定义新的和更新的实体 - 覆盖
_method_list()
和_method_get()
以自定义其输出 - 重写
\u method_create()
,\u method_update()
,\u method_delete()
并实现保存到数据库 - 使用方法修饰符处理输入dict中的自定义字段
有关如何使用crudviewmixin的示例,请参见以下实现: 测试/crud\u view.py
Attrs: _蒙哥马利: 用于处理此查询的MongoQuery对象。crudviewmixin.\u get_db_session()->;会话
(抽象方法)获取用于在此视图中进行查询的数据库会话
返回会话:sqlalchemy.orm.session
crudviewmixin.\u get_query_object()->;映射
(抽象会议hod)获取当前查询的查询对象。
注意,查询对象不仅支持get()和list()方法,而且还支持 create()、update()和delete()。这使api能够立即请求关系。
返回映射
crudviewmixin.\u method\u get(*filter,**filter\u by)->;对象
(crud方法)获取单个实体:与read一样,单个实体
通常,当用户提供了主键时使用:
{project:['login','first_name']}3
参数:
*筛选
:附加筛选()条件**筛选条件
:附加筛选条件
返回对象
例外情况:
exc.invalidQueryRor
:用户产生的查询对象错误sqlalchemy.orm.exc.multipleResultsFound
:找到多个sqlalchemy.orm.exc.noresultfound
:未找到任何内容
crudviewmixin.\u method\u list(*filter,**filter\u by)->;iterable[对象]
(crud方法)获取实体列表:与read一样,获取实体列表
通常,在用户未提供主键时使用:
{project:['login','first_name']}4
注意:小心!此方法并不总是返回实体列表! 它实际上可以返回:
- 标量值:如果是"count"查询
- dict列表:如果是"aggregate"或"group"查询
- 列表或实体:否则
请使用以下Mongoquery方法来说明发生了什么: mongoquery.result_包含_entities(),mongoquery.result_是_scalar(),mongoquery.result_是_tuples()
否则,重写以下子方法: _ method_list_result_u entities(),_method_u list_u result groups(),_method_u list_u result count()
参数:
*筛选
:附加筛选()条件**筛选条件
:附加筛选条件
返回iterable[object]
例外情况:
exc.invalidQueryRor
:用户产生的查询对象错误
crudviewmixin.\u方法创建(实体dict)->;对象
(crud方法)创建一个新实体:如create
通常,在用户未提供主键时使用:
{project:['login','first_name']}5
参数:
实体dict:dict
:实体dict
返回对象
:创建的实例(要保存)
例外情况:
exc.invalidQueryRor
:用户产生的查询对象错误
crudviewmixin.\u method\u update(实体dict,*filter,**filter\u by)->;对象
(crud方法)通过合并字段更新现有实体:如update中所示
通常,当用户提供了主键时使用:
{project:['login','first_name']}6
参数:
实体dict:dict
:实体dict*筛选
:查找上一个实体的条件**筛选依据
:查找上一个实体的条件
返回对象
:更新的实例(要保存)
例外情况:
exc.invalidQueryRor
:用户产生的查询对象错误sqlalchemy.orm.exc.multipleResultsFound
:使用筛选条件找到多个实体sqlalchemy.orm.exc.noresultfound
:找不到实体
crudviewmixin.\u method\u delete(*filter,**filter\u by)->;对象
(crud方法)删除现有实体:如delete
通常,当用户提供了主键时使用:
{project:['login','first_name']}7
请注意,它将在删除之前从数据库加载实体。
参数:
*筛选
:查找上一个实体的条件**筛选条件查找上一个实体
返回对象
:要删除的实例
例外情况:
exc.invalidQueryRor
:用户产生的查询对象错误sqlalchemy.orm.exc.multipleResultsFound
:使用筛选条件找到多个实体sqlalchemy.orm.exc.noresultfound
:找不到实体
crudviewmixin.\u mongoquery\u hook(mongoquery)->;mongoquery
(hook)在mquery()中调用的一个钩子,用于在必要时修改mongoquery
这是修改Mongoquery的最后一次机会。 在这个钩子之后,它结束()并生成一个sqlalchemy查询。
使用self.\u current_crud_方法来判断发生了什么:创建、读取、更新、删除?
参数:
mongoquery:mongoquery
:
返回mongoquery
crudviewmixin.\u save_hook(new,prev=none)
(hook)在保存实体之前,钩住create()、update()方法。
这允许在实际保存实例之前对其进行一些更改。 钩子提供了实例的旧版本和新版本(!)
参数:
新建:对象
:新实例prev:object=none
:以前保存的版本(仅在更新时提供)。
@保存关系(*字段名)
一种修饰符,用于标记一个方法,该方法处理保存一些相关模型(或任何其他自定义值)
每当一段关系在这个装饰者的帮助下被标记为保存时, 它从传入的json dict中取出,在创建实体之后, 它被传递给此装饰器装饰的方法。
除了保存关系外,还可以使用修饰的mthod保存任何自定义属性: 它们是从传入的实体dict中提取出来的,无论如何都是手动处理的。 请注意,模型上不存在的所有属性都被删除,并且是处理这些属性的唯一方法 通过这种方法。
注意:此方法在保存钩子()之前执行。
示例用法:
{project:['login','first_name']}8
注意:handler方法是用两个位置参数调用的,其余的是关键字参数:
{project:['login','first_name']}9
注意:如果用户没有提交任何相关实体,则仍然调用该方法,relationship参数为none。
可以提供多种关系:在这种情况下,所有关系都用一种方法处理。
其他有用的工具
模型属性包(模型)
模型属性包是一个类,可用于获取有关模型列的信息。
这是将它们绑定在一起的类:列、关系、pks等。 有关某个模型的所有元信息都存储在此处:
- 列
- 关系
- 主键
- 可为空的列
- 性质和混合性质
- 相关模型的列
- 可写属性
如果要检查多个属性太多,请在它们上面使用combinedbag()
,
它可以让您从多个行李中获得一列。
组合行李(**bags)
将多个包中的元素组合在一起的包。
当某个对象既可以处理列和关系,也可以处理属性和 柱。因为这取决于您在做什么,所以使用这种通用实现。
为了初始化它,您可以将所需的包作为dict提供给他们:
{'a':1,'b':1}#Includespecificfields.Allotherfieldsareexcluded{'a':0,'b':0}#Excludespecificfields.Allotherfieldsareincluded0
现在,当您得到一个项目时,您将得到您使用过的别名:
{'a':1,'b':1}#Includespecificfields.Allotherfieldsareexcluded{'a':0,'b':0}#Excludespecificfields.Allotherfieldsareincluded1
这样,您就可以始终知道列来自哪个包,并对其进行适当的处理。
计数查询(查询)
查询
可以在返回结果时计算行数的对象包装器
这是通过如下选择来实现的:
α-αα62为了透明,这个类消除了结果中的所有元组,并且仍然返回对象 就像普通的查询一样。总计数可通过属性获得。