Query Scopes and Reusable Filters
In this lesson, you will learn how to standardize your data retrieval by defining "query scopes" that turn repetitive filter logic into reusable model methods.
Why Use Query Scopes?
When building an application, you often find yourself writing the same WHERE clauses over and over. For example, if you have a User model, you might constantly need to fetch only "active" users or users who have "verified" their email addresses.
Without scopes, you might write User.find({ where: { status: 'active', verified: true } }) every time. If you ever change the definition of an "active" user (e.g., adding a deleted_at timestamp check), you would have to hunt down every single occurrence of that query across your entire codebase.
Query scopes allow you to encapsulate this logic directly inside your ORM model definition.
Implementation
Think of a query scope as a named shortcut for a query fragment. By attaching these methods to your model, you create a standard "vocabulary" for interacting with your data.
// Example using a conceptual ORM model
class User extends Model {
// Defining a reusable scope
static active() {
return this.query().where('status', 'active').where('deleted_at', null);
}
static verified() {
return this.query().where('is_verified', true);
}
}
// Now, fetching data is clean and readable:
const activeUsers = await User.active().findAll();
const verifiedActiveUsers = await User.active().verified().findAll();
The Benefits of Reusability
By moving these filters into the model, you achieve three things:
- DRY Code: You avoid "Don't Repeat Yourself" violations by defining the business logic for "active" or "verified" exactly once.
- Consistency: Every developer on your team will use the exact same criteria when querying the database, preventing bugs where one part of the app filters by status while another forgets the
deleted_atcheck. - Readability: Your application code reads like human language (
User.active()) rather than a messy list of database column names and values.
Key Takeaway: Query scopes centralize your data retrieval logic, making your codebase easier to maintain and ensuring that common filters are applied consistently across your entire application.