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
#Expressionpara definir una expresión que toma como entrada un arreglo de objetosStorage. Filtramos los almacenes dondeisEnabledseatruey retornamos el conteo de estos. - Creamos un predicado con dos condiciones:
- La propiedad
namedebe contener los caracteres especificados encriteria. - Utilizamos la expresión
storagesExpressionpara 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.