Usando predicados compuesto con SwiftData

Libranner Santos
05 febrero, 20252min de lectura
Cuando realizamos consultas a la base de datos, utilizamos condiciones con el macro #Predicate
.
La versión más simple de un predicado consiste en aplicar una sola condición. Por ejemplo:
let predicate = #Predicate<Product> {$0.name.localizedStandardContains(criteria)}
Con este código, creamos un predicado que filtra utilizando criteria
y retorna todos los objetos de tipo Product
donde la propiedad name
contenga el contenido de criteria
.
Si quieres una introducción a Swift Data, te recomendamos este artículo.
Predicados compuestos
Si necesitamos crear predicados compuestos, podemos hacer algo como lo siguiente:
let predicate = #Predicate<Trip> {$0.name.localizedStandardContains(criteria) ||$0.info.localizedStandardContains(criteria)}
En este caso, filtramos utilizando la misma condición aplicada a dos propiedades: name
o info
. El predicado retornará resultados si cualquiera de las dos cumple la condición.
Filtrado con condiciones más complejas
En ocasiones, es necesario aplicar condiciones más elaboradas. Supongamos que estamos desarrollando una aplicación de inventario y queremos realizar una consulta que retorne un listado de productos cuyo nombre contenga los caracteres especificados en la variable criteria
, pero que además exista al menos un almacén habilitado relacionado con el producto.
Para este caso, consideremos el siguiente esquema de datos:
La base de datos contiene productos (Product) que pueden estar almacenados en múltiples almacenes (Storage), estableciendo una relación de uno a muchos entre productos y almacenes.
Definimos los modelos así:
@Modelclass Storage {var location: Stringvar isEnabled: Bool}@Modelclass Product {var name: Stringvar storages: [Storage]}
El predicado que necesitamos construir se verá así:
// 1let storagesExpression = #Expression<[Storage], Int> { items initems.filter {!$0.isEnabled}.count}// 2let products = #Predicate<Product>{ product$0.name.localizedStandardContains(criteria) &&storagesExpression.evaluate(product.storages) > 0}
En este código:
- Usamos
#Expression
para definir una expresión que toma como entrada un arreglo de objetosStorage
. Filtramos los almacenes dondeisEnabled
seatrue
y retornamos el conteo de estos. - Creamos un predicado con dos condiciones:
- La propiedad
name
debe contener los caracteres especificados encriteria
. - Utilizamos la expresión
storagesExpression
para evaluar los almacenes relacionados con el producto, asegurando que el resultado del conteo sea mayor a cero.
- La propiedad
Conclusión
Gracias a los predicados, podemos realizar consultas a las bases de datos de manera eficiente. Si combinamos esto con el uso de #Expression
, es posible crear consultas más complejas y adaptadas a escenarios específicos.