Saltar al contenido principal

Predicados

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Predicados de campos

  • Bool:

    • =, !=
  • Numeric:

    • =, !=, >, <, >=, <=,
    • IN, NOT IN
  • Time:

    • =, !=, >, <, >=, <=
    • IN, NOT IN
  • String:

    • =, !=, >, <, >=, <=
    • IN, NOT IN
    • Contains, HasPrefix, HasSuffix
    • ContainsFold, EqualFold (SQL specific)
  • JSON

    • =, !=
    • =, !=, >, <, >=, <= on nested values (JSON path).
    • Contains on nested values (JSON path).
    • HasKey, Len<P>
    • null checks for nested values (JSON path).
  • Campos opcionales:

    • IsNil, NotNil

Predicados de aristas

  • HasEdge. Por ejemplo, para una arista llamada owner de tipo Pet, usa:

     client.Pet.
    Query().
    Where(pet.HasOwner()).
    All(ctx)
  • HasEdgeWith. Añade una lista de predicados para el predicado de arista.

     client.Pet.
    Query().
    Where(pet.HasOwnerWith(user.Name("a8m"))).
    All(ctx)

Negación (NOT)

client.Pet.
Query().
Where(pet.Not(pet.NameHasPrefix("Ari"))).
All(ctx)

Disyunción (OR)

client.Pet.
Query().
Where(
pet.Or(
pet.HasOwner(),
pet.Not(pet.HasFriends()),
)
).
All(ctx)

Conjunción (AND)

client.Pet.
Query().
Where(
pet.And(
pet.HasOwner(),
pet.Not(pet.HasFriends()),
)
).
All(ctx)

Predicados personalizados

Los predicados personalizados son útiles para implementar lógica específica de un dialecto o controlar las consultas ejecutadas.

Obtener todas las mascotas de los usuarios 1, 2 y 3

pets := client.Pet.
Query().
Where(func(s *sql.Selector) {
s.Where(sql.InInts(pet.FieldOwnerID, 1, 2, 3))
}).
AllX(ctx)

El código anterior generará la siguiente consulta SQL:

SELECT DISTINCT `pets`.`id`, `pets`.`owner_id` FROM `pets` WHERE `owner_id` IN (1, 2, 3)

Contar usuarios cuyo campo JSON URL contiene la clave Scheme

count := client.User.
Query().
Where(func(s *sql.Selector) {
s.Where(sqljson.HasKey(user.FieldURL, sqljson.Path("Scheme")))
}).
CountX(ctx)

El código anterior generará la siguiente consulta SQL:

-- PostgreSQL
SELECT COUNT(DISTINCT "users"."id") FROM "users" WHERE "url"->'Scheme' IS NOT NULL

-- SQLite and MySQL
SELECT COUNT(DISTINCT `users`.`id`) FROM `users` WHERE JSON_EXTRACT(`url`, "$.Scheme") IS NOT NULL

Obtener todos los usuarios con un coche "Tesla"

Considera una consulta ent como:

users := client.User.Query().
Where(user.HasCarWith(car.Model("Tesla"))).
AllX(ctx)

Esta consulta puede reformularse de 3 formas: IN, EXISTS y JOIN.

// `IN` version.
users := client.User.Query().
Where(func(s *sql.Selector) {
t := sql.Table(car.Table)
s.Where(
sql.In(
s.C(user.FieldID),
sql.Select(t.C(user.FieldID)).From(t).Where(sql.EQ(t.C(car.FieldModel), "Tesla")),
),
)
}).
AllX(ctx)

// `JOIN` version.
users := client.User.Query().
Where(func(s *sql.Selector) {
t := sql.Table(car.Table)
s.Join(t).On(s.C(user.FieldID), t.C(car.FieldOwnerID))
s.Where(sql.EQ(t.C(car.FieldModel), "Tesla"))
}).
AllX(ctx)

// `EXISTS` version.
users := client.User.Query().
Where(func(s *sql.Selector) {
t := sql.Table(car.Table)
p := sql.And(
sql.EQ(t.C(car.FieldModel), "Tesla"),
sql.ColumnsEQ(s.C(user.FieldID), t.C(car.FieldOwnerID)),
)
s.Where(sql.Exists(sql.Select().From(t).Where(p)))
}).
AllX(ctx)

El código anterior generará la siguiente consulta SQL:

-- `IN` version.
SELECT DISTINCT `users`.`id`, `users`.`age`, `users`.`name` FROM `users` WHERE `users`.`id` IN (SELECT `cars`.`owner_id` FROM `cars` WHERE `cars`.`model` = 'Tesla')

-- `JOIN` version.
SELECT DISTINCT `users`.`id`, `users`.`age`, `users`.`name` FROM `users` JOIN `cars` ON `users`.`id` = `cars`.`owner_id` WHERE `cars`.`model` = 'Tesla'

-- `EXISTS` version.
SELECT DISTINCT `users`.`id`, `users`.`age`, `users`.`name` FROM `users` WHERE EXISTS (SELECT * FROM `cars` WHERE `cars`.`model` = 'Tesla' AND `users`.`id` = `cars`.`owner_id`)

Obtener mascotas cuyo nombre coincide con un patrón

El código generado incluye los predicados HasPrefix, HasSuffix, Contains y ContainsFold para coincidencias de patrones. Para usar el operador LIKE con un patrón personalizado, sigue este ejemplo:

pets := client.Pet.Query().
Where(func(s *sql.Selector){
s.Where(sql.Like(pet.Name,"_B%"))
}).
AllX(ctx)

El código anterior generará la siguiente consulta SQL:

SELECT DISTINCT `pets`.`id`, `pets`.`owner_id`, `pets`.`name`, `pets`.`age`, `pets`.`species` FROM `pets` WHERE `name` LIKE '_B%'

Funciones SQL personalizadas

Para usar funciones SQL incorporadas como DATE(), emplea una de estas opciones:

1. Pasa una función de predicado compatible con el dialecto usando la opción sql.P:

users := client.User.Query().
Select(user.FieldID).
Where(func(s *sql.Selector) {
s.Where(sql.P(func(b *sql.Builder) {
b.WriteString("DATE(").Ident("last_login_at").WriteByte(')').WriteOp(OpGTE).Arg(value)
}))
}).
AllX(ctx)

El código anterior generará la siguiente consulta SQL:

SELECT `id` FROM `users` WHERE DATE(`last_login_at`) >= ?

2. Inserta una expresión de predicado usando la opción ExprP():

users := client.User.Query().
Select(user.FieldID).
Where(func(s *sql.Selector) {
s.Where(sql.ExprP("DATE(last_login_at) >= ?", value))
}).
AllX(ctx)

El código anterior generará la misma consulta SQL:

SELECT `id` FROM `users` WHERE DATE(`last_login_at`) >= ?

Predicados JSON

Los predicados JSON no se generan por defecto. No obstante, ent proporciona un paquete oficial llamado sqljson para aplicar predicados en columnas JSON usando la opción de predicados personalizados.

Comparar un valor JSON

sqljson.ValueEQ(user.FieldData, data)

sqljson.ValueEQ(user.FieldURL, "https", sqljson.Path("Scheme"))

sqljson.ValueNEQ(user.FieldData, content, sqljson.DotPath("attributes[1].body.content"))

sqljson.ValueGTE(user.FieldData, status.StatusBadRequest, sqljson.Path("response", "status"))

Comprobar la existencia de una clave JSON

sqljson.HasKey(user.FieldData, sqljson.Path("attributes", "[1]", "body"))

sqljson.HasKey(user.FieldData, sqljson.DotPath("attributes[1].body"))

Ten en cuenta que una clave con el valor literal null también coincide con esta operación.

Verificar literales JSON null

sqljson.ValueIsNull(user.FieldData)

sqljson.ValueIsNull(user.FieldData, sqljson.Path("attributes"))

sqljson.ValueIsNull(user.FieldData, sqljson.DotPath("attributes[1].body"))

Nota: ValueIsNull devuelve verdadero si el valor es null en JSON,
pero no si es NULL en la base de datos.

Comparar la longitud de un array JSON

sqljson.LenEQ(user.FieldAttrs, 2)

sql.Or(
sqljson.LenGT(user.FieldData, 10, sqljson.Path("attributes")),
sqljson.LenLT(user.FieldData, 20, sqljson.Path("attributes")),
)

Verificar si un valor JSON contiene otro valor

sqljson.ValueContains(user.FieldData, data)

sqljson.ValueContains(user.FieldData, attrs, sqljson.Path("attributes"))

sqljson.ValueContains(user.FieldData, code, sqljson.DotPath("attributes[0].status_code"))

Verificar si un valor de cadena JSON contiene una subcadena dada o tiene un sufijo/prefijo específico

sqljson.StringContains(user.FieldURL, "github", sqljson.Path("host"))

sqljson.StringHasSuffix(user.FieldURL, ".com", sqljson.Path("host"))

sqljson.StringHasPrefix(user.FieldData, "20", sqljson.DotPath("attributes[0].status_code"))

Verificar si un valor JSON es igual a cualquiera de los valores en una lista

sqljson.ValueIn(user.FieldURL, []any{"https", "ftp"}, sqljson.Path("Scheme"))

sqljson.ValueNotIn(user.FieldURL, []any{"github", "gitlab"}, sqljson.Path("Host"))

Comparación de Campos

El paquete dialect/sql proporciona un conjunto de funciones de comparación que pueden usarse para comparar campos en una consulta.

client.Order.Query().
Where(
sql.FieldsEQ(order.FieldTotal, order.FieldTax),
sql.FieldsNEQ(order.FieldTotal, order.FieldDiscount),
).
All(ctx)

client.Order.Query().
Where(
order.Or(
sql.FieldsGT(order.FieldTotal, order.FieldTax),
sql.FieldsLT(order.FieldTotal, order.FieldDiscount),
),
).
All(ctx)