智能选择字段
在 GORM 中,您可以使用 Select
方法高效地选择特定字段。这在处理大型模型但只需要一部分字段时特别有用,尤其是在 API 响应中。
type User struct { |
注意 在
QueryFields
模式下,所有模型字段都通过其名称进行选择。
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{ |
锁定
GORM 支持不同类型的锁,例如
// Basic FOR UPDATE lock |
上述语句将在事务期间锁定所选行。这可用于您准备更新行并希望防止其他事务在您的事务完成之前修改它们的情况。
Strength
也可以设置为 SHARE
,这将以允许其他事务读取锁定行但不更新或删除它们的方式锁定行。
db.Clauses(clause.Locking{ |
Table
选项可用于指定要锁定的表。当您连接多个表并且只想锁定其中一个表时,这很有用。
可以提供诸如 NOWAIT
之类的选项,如果锁不可用,它会尝试获取锁并立即失败并返回错误。它可以防止事务等待其他事务释放其锁。
db.Clauses(clause.Locking{ |
另一个选项是 SKIP LOCKED
,它会跳过已被其他事务锁定的任何行。这在高并发情况下很有用,您希望处理当前未被其他事务锁定的行。
有关更高级的锁定策略,请参阅 原始 SQL 和 SQL 生成器。
子查询
子查询是 SQL 中的一个强大功能,允许嵌套查询。当使用 *gorm.DB 对象作为参数时,GORM 可以自动生成子查询。
// Simple subquery |
来自子查询
GORM 允许在 FROM 子句中使用子查询,从而实现复杂的查询和数据组织。
// Using subquery in FROM clause |
分组条件
GORM 中的分组条件提供了一种更具可读性和可维护性的方式来编写涉及多个条件的复杂 SQL 查询。
// Complex SQL query using Group Conditions |
多列 IN
GORM 支持多列 IN 子句,允许您在单个查询中根据多个字段值过滤数据。
// Using IN with multiple columns |
命名参数
GORM 通过支持命名参数来增强 SQL 查询的可读性和可维护性。此功能允许更清晰、更有条理地构建查询,尤其是在具有多个参数的复杂查询中。可以使用 sql.NamedArg
或 map[string]interface{}{}
来利用命名参数,从而在如何构建查询方面提供灵活性。
// Example using sql.NamedArg for named arguments |
有关更多示例和详细信息,请参阅 原始 SQL 和 SQL 生成器
查找至映射
GORM 通过允许将结果扫描到 map[string]interface{}
或 []map[string]interface{}
中来提供查询数据的灵活性,这对于动态数据结构非常有用。
在使用 Find To Map
时,在查询中包含 Model
或 Table
以明确指定表名至关重要。这确保 GORM 理解要查询哪个表。
// Scanning the first result into a map with Model |
FirstOrInit
GORM 的 FirstOrInit
方法用于获取与给定条件匹配的第一条记录,如果未找到匹配记录,则初始化一个新实例。此方法兼容结构体和映射条件,并允许使用 Attrs
和 Assign
方法进行额外的灵活操作。
// If no User with the name "non_existing" is found, initialize a new User |
使用 Attrs
进行初始化
如果未找到记录,则可以使用 Attrs
使用其他属性初始化结构体。这些属性包含在新结构体中,但不用于 SQL 查询。
// If no User is found, initialize with given conditions and additional attributes |
使用 Assign
设置属性
无论是否找到记录,Assign
方法都允许您在结构体上设置属性。这些属性设置在结构体上,但不用于构建 SQL 查询,最终数据也不会保存到数据库中。
// Initialize with given conditions and Assign attributes, regardless of record existence |
FirstOrInit
以及 Attrs
和 Assign
提供了一种强大而灵活的方式,只需一步即可确保记录存在并使用特定属性进行初始化或更新。
FirstOrCreate
GORM 中的 FirstOrCreate
用于获取与给定条件匹配的第一条记录,如果未找到匹配记录,则创建一个新记录。此方法对结构体和映射条件都有效。 RowsAffected
属性用于确定创建或更新的记录数。
// Create a new record if not found |
将 Attrs
与 FirstOrCreate 一起使用
如果未找到记录,则可以使用 Attrs
为新记录指定其他属性。这些属性用于创建,但不用于初始搜索查询。
// Create a new record with additional attributes if not found |
将 Assign
与 FirstOrCreate 一起使用
无论是否找到记录,Assign
方法都会在记录上设置属性,并且这些属性会保存回数据库。
// Initialize and save new record with `Assign` attributes if not found |
优化器/索引提示
GORM 包括对优化器和索引提示的支持,允许您影响查询优化器的执行计划。这在优化查询性能或处理复杂查询时特别有用。
优化器提示是建议数据库的查询优化器应如何执行查询的指令。GORM 通过 gorm.io/hints 包促进优化器提示的使用。
import "gorm.io/hints" |
索引提示
索引提示为数据库提供有关使用哪些索引的指导。如果查询计划程序没有为查询选择最有效的索引,则它们可能会有所帮助。
import "gorm.io/hints" |
这些提示会显着影响查询性能和行为,尤其是在大型数据库或复杂数据模型中。有关更多详细信息和其他示例,请参阅 GORM 文档中的优化器提示/索引/注释。
迭代
GORM 支持使用 Rows
方法迭代查询结果。当您需要处理大型数据集或分别对每条记录执行操作时,此功能特别有用。
您可以遍历查询返回的行,将每一行扫描到一个结构体中。此方法提供了对如何处理每条记录的粒度控制。
rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Rows() |
此方法非常适用于无法使用标准查询方法轻松实现的复杂数据处理。
FindInBatches
FindInBatches
允许批量查询和处理记录。这对于有效处理大型数据集、减少内存使用和提高性能特别有用。
使用 FindInBatches
,GORM 以指定的批处理大小处理记录。在批处理函数内部,您可以对每批记录应用操作。
// Processing records in batches of 100 |
FindInBatches
是一种有效的工具,用于以可管理的块处理大量数据,优化资源使用和性能。
查询钩子
GORM 提供了使用钩子的功能,例如 AfterFind
,它会在查询的生命周期中触发。这些钩子允许在特定时间点执行自定义逻辑,例如从数据库中检索记录之后。
此钩子对于查询后数据操作或默认值设置非常有用。有关更多详细信息和其他钩子类型,请参阅 GORM 文档中的钩子。
func (u *User) AfterFind(tx *gorm.DB) (err error) { |
提取
GORM 中的 Pluck
方法用于从数据库中查询单个列,并将结果扫描到切片中。当您需要从模型中检索特定字段时,此方法非常理想。
如果您需要查询多个列,则可以使用 Select
和 Scan 或 Find。
// Retrieving ages of all users |
作用域
GORM 中的 Scopes
是一项强大的功能,允许您将常用的查询条件定义为可重用方法。这些作用域可以在您的查询中轻松引用,使您的代码更具模块化和可读性。
定义作用域
Scopes
被定义为修改并返回 gorm.DB
实例的函数。您可以根据应用程序的需求将各种条件定义为作用域。
// Scope for filtering records where amount is greater than 1000 |
在查询中应用作用域
您可以使用 Scopes
方法将一个或多个作用域应用于查询。这允许您动态地链接多个条件。
// Applying scopes to find all credit card orders with an amount greater than 1000 |
Scopes
是一种简洁高效地封装常见查询逻辑的方法,可增强代码的可维护性和可读性。有关更详细的示例和用法,请参阅 GORM 文档中的作用域。
计数
GORM 中的 Count
方法用于检索与给定查询匹配的记录数。它是一个有用的功能,用于了解数据集的大小,特别是在涉及条件查询或数据分析的情况下。
获取匹配记录数
您可以使用 Count
来确定查询中满足特定条件的记录数。
var count int64 |
使用 Distinct 和 Group 进行计数
GORM 还允许对不同值进行计数并对结果进行分组。
// Counting distinct names |