以sqlalchemy为后端的json查询引擎

mongosql的Python项目详细描述


构建状态pythons

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进行测试。

目录

查询

如果您知道如何在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']}
  • 对象语法。

    提供映射到a1(include)或a0(exclude)的字段名对象。

    示例:

    {'a':1,'b':1}#Includespecificfields.Allotherfieldsareexcluded{'a':0,'b':0}#Excludespecificfields.Allotherfieldsareincluded

    注意,不能将两者混合使用:要么使用all1s指定要包含的字段, 或者使用all0s指定要排除的字段。

    注意:一种特殊情况是所谓的"完全投影":当投影对象提到每个属性时 对于一个模型,您可以将1s设置为某些,并将0s设置为同一对象中的其他。明智使用。

默认情况下排除的字段

请注意,默认情况下,模型中存在的某些字段可能不包括在中:这是 后端开发人员可能在服务器上配置了默认排除设置。

除非明确要求,否则将不会接收这些字段。 这可能适用于包含大量数据或需要进行一些计算的某些字段。

要包含这些字段,必须显式地请求它们:只需使用它们的名称 在您请求的字段列表中。

相关型号

通常,为了加载相关模型(例如,用户的用户配置文件,或与此模型相关的一些其他数据)。 您可以使用连接操作。

不过,为了方便起见,现在还可以通过在投影中指定相关模型的名称来加载它们, 好像是一片田野。例如:

{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}-值的和

    操作数可以是:

    • 列名:将聚合函数应用于列

      示例:

      GET /api/user?query={"filter":{"age":{"$gte":18}}}
      
      0
    • 布尔表达式:请参见过滤操作。

      这是一个非常有用的技巧。 因为布尔表达式的结果是1当它为真时,可以取它们的$sum, 并计算与该条件匹配的行数。

      示例:

      GET /api/user?query={"filter":{"age":{"$gte":18}}}
      
      1
    • 整数值(仅由$sum运算符支持)

      示例:

      GET /api/user?query={"filter":{"age":{"$gte":18}}}
      
      2

请注意,聚合通常只有在与组操作一起使用时才有意义

组操作

分组对应于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

语法

如您所见,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查询对象。

有两种使用方法:

  1. 手动构造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
  2. 为您的基地使用便利混音:

    {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不可重用:它只能进行一次查询。

但是,保存一些初始化并为新请求做好准备是有意义的。 出于性能原因,这必须使用可重用的包装器手动完成

{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()

一旦准备好MongoQuery,就可以给它一个QueryObject:

$.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

得到各种结果

让我们记住,mongoquery生成的查询可以返回三种结果:

  1. 实体。当api用户请求一个列表的实体时。
  2. 整数。当api用户使用了{count:1}
  3. Tuples .这是api用户使用聚合操作时得到的结果。

mongoquery有三种方法可以帮助您检测得到的信息:

  1. mongoquery.result_包含实体()
  2. mongoquery.result_是_scalar()
  3. mongoquery.result_是元组()

使用方法如下:

$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
2

很可能,您根本不需要处理这个问题:只需使用crud helpers 为您实现大部分逻辑。

MongoQuery配置

mongoquery有很多设置,可以让您配置查询的方式, 微调它们的安全限制,并实现一些自定义行为。

这些设置可以很好地保存在amongoquerysettingsdict中 作为第二个参数给Mongoquery。

示例:

$.get('/api/user?query='+JSON.stringify({// only include the following fieldsproject:['id','first_name','last_name'],}))
3

可用的设置为:

  • 默认投影:(用于:项目) 未提供输入时使用的默认投影。 当给定一个输入值时,default_projection根本不使用:它覆盖默认值 完全。如果要将某些默认值合并到每个投影中,请使用以下某些设置: 默认排除强制排除强制排除

    注意:如果希望api默认返回所有字段,请使用none。如果你想让api 默认情况下,使用空列表。 这是因为none被视为"无默认",而mongosql使用其内部默认值包括 所有字段;但[]被视为"默认不包含字段"的指令。

  • 默认排除(for:project) 从每个投影中排除的属性列表。 加载这些属性的唯一方法是显式地请求它们。 对于包含大量数据或需要额外查询的属性,请使用此选项。

  • 默认排除属性:(用于:项目) 当true时,所有@属性@混合属性属性 默认情况下将被排除(放入default_exclude)。 这是一条方便的捷径。 使用默认包含属性否决。

  • 默认未包含属性:(用于:项目) 不排除的@property@hybrid\u property属性列表: 它们将被视为其他列。

  • 捆绑项目:(用于:项目) 声明依赖于正在加载的其他列的列的dict。 当您有一个依赖于某些列的属性,并且用户希望加载它时,setti天然气 已将属性的名称映射到依赖列的列表。 示例:{'全名':['名字','姓氏']}

  • 强制包含(for:project) 始终加载并包含在输出中的属性列表。

  • 强制排除(for:project) 始终从输出中卸载和排除的属性列表。 无论您做什么,都无法访问它们。

  • 确保已加载(for:project) 即使用户没有请求也将加载的列的列表。 但是,这些列将安静地加载,而不包括在投影中。 用例:代码所需的列。如果没有它们,它会崩溃,以防用户排除它们。 您不希望强制包含它们,但希望"悄悄"包含它们。

  • (用于:项目) granularraiseload:仅当延迟加载列时才升高

  • raiseload_rel(用于:连接) granularraiseload:仅当延迟加载关系时才升高

  • raiseload:(用于:项目,联接) 当未加载列或关系时引发异常 由应用程序访问。 这将导致额外的SQL查询,查询速度非常慢。

    这是一种性能保护:当api用户不需要某些列时, 它们没有装载。但是,当应用程序试图访问它们时。 当raiseload_col=true时,需要手动加载所有列和关系 (使用undefer()joinedload())或使用mongoquery.ensure_loaded()

  • 聚合列:(用于:聚合) 启用聚合的列名列表。 未显式启用聚合的所有列都将被禁用。

  • 聚合标签:(用于:聚合) 是否启用标记列(别名)。 这些功能基本上是无用的, 但在这里存在是为了完成与MongoDB查询的兼容性。

  • 强制过滤器:(用于:过滤器) 一本字典,它有一个过滤器,每个请求都会被强制执行; 或者返回query.filter()过滤条件的python可调用(模型)

  • 标量运算符:(for:filter) 标量列的附加运算符的指令。 声明全局运算符的更好方法是将mongofilter子类 并声明类中的其他运算符。

  • 数组运算符(for:filter) 数组列的附加运算符的dict。

  • 允许的关联:(for:join) 用户可以加载的关系的显式列表。 当尝试"加入"时,所有其他关系都将引发DisablederRor。

  • 禁止的关系(for:join) 将引发用户无法加载的关系列表:disablederror。

  • 最大项目数:(用于:限制) 此查询可以加载的最大项数。 用户永远不能超过这个值,这个值会被强制加载到每个查询中。

  • 旧字段:(用于:所有内容) 以前存在但不再存在的字段(列、关系)列表。 所有的处理者都会悄悄地忽略这些领域。请注意,它们仍将出现在投影中 从projectjoin处理程序。如果你依赖它们,你的代码将不得不忽略 这些字段也是。

    这是为了在开发人员可能仍然引用 到不再存在的旧列。

    当关系或列从模型中消失时,建议 向后兼容的方法是使两者都小于code>传统字段强制包含, 以及一个@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()

限制:

  1. 如果用户已请求对关系进行筛选,则不能对其使用"确保已加载"()。 此方法将引发invalidQueryRor()。 这是有道理的,因为如果应用程序代码依赖于某种关系的存在, 它当然需要完全加载和未过滤。
  2. 如果请求不包含任何实体(例如使用"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中获取一些信息时。

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:要使用的查询对象

  • from_query:union[sqlalchemy.orm.query.query,nonetype]=none:用

    初始化MongoQuery的可选查询

返回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:只读属性名列表,或提供列表的callable

  • rw\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视图:

  1. 实现从请求中提取查询对象的方法
  2. 在类级别设置crudhelper,用正确的设置初始化它
  3. 实现_get_db_session()_get_query_object()方法
  4. 如有必要,执行\u save_hook()以自定义新的和更新的实体
  5. 覆盖_method_list()_method_get()以自定义其输出
  6. 重写\u method_create()\u method_update()\u method_delete()并实现保存到数据库
  7. 使用方法修饰符处理输入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

注意:小心!此方法并不总是返回实体列表! 它实际上可以返回:

  1. 标量值:如果是"count"查询
  2. dict列表:如果是"aggregate"或"group"查询
  3. 列表或实体:否则

请使用以下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.Allotherfieldsareincluded
0

现在,当您得到一个项目时,您将得到您使用过的别名:

{'a':1,'b':1}#Includespecificfields.Allotherfieldsareexcluded{'a':0,'b':0}#Excludespecificfields.Allotherfieldsareincluded
1

这样,您就可以始终知道列来自哪个包,并对其进行适当的处理。

计数查询(查询)

查询可以在返回结果时计算行数的对象包装器

这是通过如下选择来实现的:

α-αα62

为了透明,这个类消除了结果中的所有元组,并且仍然返回对象 就像普通的查询一样。总计数可通过属性获得。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
在Maven的其他模块中看不到依赖模块中的java更改   http使用Java提交HTML表单数据,以检索从jsp应用程序下载的内容   因此,java JPA直接获取一个映射,而不是对象列表   java Dagger2:如何在多态性期间注入成员变量?   java如何在playFramework中重用控制器类的功能   java JavaMail到minecraft   java如何在RecyclerView滚动上下载更多Firebase对象?   PDFBOX org出现java Proc Groovy错误。阿帕奇。pdfbox。余弦。COSDocument finalize警告:警告:您没有关闭PDF文档   用java将英语翻译成本地语言   javascript不使用servlet将JSON对象传递给Java类   数据结构二进制搜索树泛型Java   如何在cmd中使用jar编译和执行java?   java如何用JPA连接表列?   java 2D Arraylist预测代码的输出   Java:“历史”对于cli命令,如何使输出“可编辑”?