TinyORM: Collections
Introduction
The Orm::Tiny::Types::ModelsCollection
is specialized container which provides a fluent, convenient wrapper for working with vector of models. All TinyORM methods that return more than one model result, will return instances of the ModelsCollection
class, including results retrieved via the get
method or methods that return relationships like the getRelation
and getRelationValue
.
The ModelsCollection
class extends QVector<Model>
, so it naturally inherits dozens of methods used to work with the underlying vector of TinyORM models. Be sure to review the QList
documentation to learn all about these helpful methods!
The ModelsCollection
template parameter can be declared only with the model type or a model type pointer, it also can't be const
and can't be a reference. It's constrained using the DerivedCollectionModel
concept.
You can iterate over the ModelsCollection
the same way as over the QVector
:
using Models::User;
ModelsCollection<User> users = User::whereEq("active", true)->get();
for (const auto &user : users)
qDebug() << user.getAttribute<QString>("name");
However, as previously mentioned, collections are much more powerful than vectors and expose a variety of map / reduce operations that may be chained using an intuitive interface. For example, we may remove all active users and then gather the first name of each remaining user:
auto names = User::all().reject([](User *const user)
{
return user->getAttribute<bool>("active");
})
.pluck("name");
As you can see, the ModelsCollection
class allows you to chain its methods to perform fluent mapping and reducing of the underlying vector. In general, collections are immutable, meaning every ModelsCollection
method returns an entirely new ModelsCollection
instance.
The ModelsCollection<Model>
is returning from the Models' methods like get
, all
, findMany
, chunk
; the ModelsCollection<Model *>
is returning from the relationship-related methods as getRelation
and getRelationValue
.
Collection Conversion
While most TinyORM collection methods return a new instance of ModelsCollection
, the modelKeys
, mapWithKeys
, and pluck
methods return a base QVector or std unordered/map instances. Likewise, one of the map
methods overload returns the QVector<T>
.
Creating Collections
Creating a ModelsCollection
is as simple as:
ModelsCollection<User> users {
{{"name", "Kate"}, {"votes", 150}},
{{"name", "John"}, {"votes", 200}},
};
You can also create a collection of pointers, eg. ModelsCollection<User *>
:
ModelsCollection<User *> userPointers {
&users[0], &users[1],
};
The ModelsCollection<Model>
is implicitly convertible and assignable from the QVector<Model>
:
QVector<User> usersVector {
{{"name", "Kate"}, {"votes", 150}},
{{"name", "John"}, {"votes", 200}},
};
ModelsCollection<User> users(usersVector);
users = usersVector;
Alternatively, you can use the Orm::collect<Model>
helper function to create a ModelsCollection
from the given attributes:
ModelsCollection<User> users = Orm::collect<User>({
{{"name", "Kate"}, {"added_on", QDateTime::currentDateTimeUtc()}},
{{"name", "John"}, {"added_on", QDateTime({2023, 6, 1}, {13, 46, 15}, QTimeZone::UTC)}},
});
The Orm::collect<Model>
function is mandatory if your attributes contain the QDateTime
instance, you can read more about this problem here.
The results of TinyORM queries are always returned as ModelsCollection
instances.
Available Methods
For the majority of the remaining collection documentation, we'll discuss each method available on the ModelsCollection
class. Remember, all of these methods may be chained to fluently manipulate the underlying vector.
Furthermore, almost every method returns a new ModelsCollection
instance, allowing you to preserve the original copy of the collection when necessary:
all contains doesntContain each except filter find first firstWhere fresh implode isEmpty isNotEmpty last load map mapWithKeys mapWithModelKeys modelKeys only pluck reject sort sortBy sortByDesc sortDesc stableSort stableSortBy stableSortByDesc stableSortDesc tap toBase toJson toJsonArray toJsonDocument toMap toMapVariantList toQuery toVector toVectorVariantList unique uniqueBy uniqueRelaxed uniqueRelaxedBy value where whereBetween whereIn whereNotBetween whereNotIn whereNotNull whereNull
For a better understanding of the following examples, many of the variable declarations below use actual types instead of the auto
keyword.