Backbone Collection Methods — Filtering, Sorting, and Querying Data
In this tutorial, you will learn about Backbone Collection Methods. We cover key concepts, practical examples, and best practices to help you master this topic.
Backbone Collections inherit Underscore.js methods for data processing. Methods like each, pluck, where, findWhere, filter, sortBy, and groupBy let you query and transform collection data with expressive, chainable syntax.
What You'll Learn
You'll learn all major Collection methods for iteration, filtering, sorting, grouping, and aggregation. You'll see how Underscore integration makes Backbone Collections powerful data-processing tools.
Why It Matters
Real applications filter, sort, and aggregate data constantly. Showing only high-priority alerts, grouping tasks by category, or finding the top 10 results are everyday operations. Collection methods make these tasks concise and readable.
Real-World Use
A network monitoring tool groups incidents by severity, filters for unresolved ones, sorts by timestamp, and computes average response time — all using Collection methods chained together.
flowchart LR
A[Collection] --> B[filter]
B --> C[sortBy]
C --> D[groupBy]
D --> E[each]
E --> F[pluck]
F --> G[Display]
Iteration: each and map
each iterates over every model. map transforms each model and returns a new array.
var Task = Backbone.Model.extend({ defaults: { title: '', priority: '' } });
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'Fix bug', priority: 'high' },
{ title: 'Write tests', priority: 'medium' },
{ title: 'Update docs', priority: 'low' }
]);
// each — iterate
tasks.each(function(task) {
console.log(task.get('title') + ' (' + task.get('priority') + ')');
});
// map — transform
var titles = tasks.map(function(task) {
return task.get('title').toUpperCase();
});
console.log('Uppercased:', titles);
Expected output:
Fix bug (high)
Write tests (medium)
Update docs (low)
Uppercased: ['FIX BUG', 'WRITE TESTS', 'UPDATE DOCS']
Querying: where and findWhere
where returns an array of matching models. findWhere returns the first match.
var Task = Backbone.Model.extend({ defaults: { title: '', priority: '', done: false } });
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'Task A', priority: 'high', done: false },
{ title: 'Task B', priority: 'high', done: true },
{ title: 'Task C', priority: 'low', done: false },
{ title: 'Task D', priority: 'medium', done: false }
]);
var highPriority = tasks.where({ priority: 'high' });
console.log('High priority count:', highPriority.length);
var firstHigh = tasks.findWhere({ priority: 'high' });
console.log('First high priority:', firstHigh.get('title'));
var incompleteHigh = tasks.where({ priority: 'high', done: false });
console.log('Incomplete high count:', incompleteHigh.length);
Expected output:
High priority count: 2
First high priority: Task A
Incomplete high count: 1
Advanced Filtering: filter and reject
filter returns models where the callback returns true. reject returns the opposite.
var Alert = Backbone.Model.extend({ defaults: { message: '', severity: '' } });
var AlertList = Backbone.Collection.extend({ model: Alert });
var alerts = new AlertList([
{ message: 'CPU overload', severity: 'critical' },
{ message: 'Disk warning', severity: 'warning' },
{ message: 'Info update', severity: 'info' },
{ message: 'Memory leak', severity: 'critical' }
]);
var criticalAlerts = alerts.filter(function(alert) {
return alert.get('severity') === 'critical';
});
console.log('Critical alerts:', criticalAlerts.length);
var nonCritical = alerts.reject(function(alert) {
return alert.get('severity') === 'critical';
});
console.log('Non-critical:', nonCritical.length);
Expected output:
Critical alerts: 2
Non-critical: 2
Sorting: sortBy
sortBy returns a new array sorted by the result of the callback. Does not change the Collection's internal order.
var Task = Backbone.Model.extend({ defaults: { title: '', priority: 0 } });
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'Alpha', priority: 3 },
{ title: 'Beta', priority: 1 },
{ title: 'Gamma', priority: 2 }
]);
var byPriority = tasks.sortBy(function(task) {
return task.get('priority');
});
console.log('Sorted by priority:', byPriority.map(function(m) { return m.get('title'); }));
var byTitle = tasks.sortBy(function(task) {
return task.get('title');
});
console.log('Sorted by title:', byTitle.map(function(m) { return m.get('title'); }));
Expected output:
Sorted by priority: ['Beta', 'Gamma', 'Alpha']
Sorted by title: ['Alpha', 'Beta', 'Gamma']
Grouping: groupBy and countBy
groupBy groups models by a property. countBy returns counts per group.
var Task = Backbone.Model.extend({ defaults: { title: '', category: '' } });
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'Design API', category: 'backend' },
{ title: 'Build UI', category: 'frontend' },
{ title: 'Write tests', category: 'backend' },
{ title: 'Setup CI', category: 'devops' },
{ title: 'Create mockups', category: 'frontend' }
]);
var byCategory = tasks.groupBy(function(task) {
return task.get('category');
});
console.log('Backend tasks:', byCategory.backend.length);
console.log('Frontend tasks:', byCategory.frontend.length);
var counts = tasks.countBy(function(task) {
return task.get('category');
});
console.log('Counts:', counts);
Expected output:
Backend tasks: 2
Frontend tasks: 2
Counts: { backend: 2, frontend: 2, devops: 1 }
Pluck and Invoke
pluck extracts a single attribute from every model. invoke calls a method on every model.
var Task = Backbone.Model.extend({
defaults: { title: '', rating: 0 },
shout: function() {
return this.get('title').toUpperCase() + '!';
}
});
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'Alpha', rating: 5 },
{ title: 'Beta', rating: 3 },
{ title: 'Gamma', rating: 4 }
]);
console.log('All titles:', tasks.pluck('title'));
console.log('All ratings:', tasks.pluck('rating'));
console.log('Shouted:', tasks.invoke('shout'));
Expected output:
All titles: ['Alpha', 'Beta', 'Gamma']
All ratings: [5, 3, 4]
Shouted: ['ALPHA!', 'BETA!', 'GAMMA!']
Chaining with Chain
The chain() method enables fluent method chaining.
var Task = Backbone.Model.extend({ defaults: { title: '', priority: '', done: false } });
var TaskList = Backbone.Collection.extend({ model: Task });
var tasks = new TaskList([
{ title: 'A', priority: 'high', done: false },
{ title: 'B', priority: 'high', done: true },
{ title: 'C', priority: 'low', done: false },
{ title: 'D', priority: 'medium', done: true }
]);
var result = tasks.chain()
.filter(function(t) { return !t.get('done'); })
.sortBy(function(t) { return t.get('priority'); })
.pluck('title')
.value();
console.log('Incomplete sorted:', result);
Expected output:
Incomplete sorted: ['C', 'D', 'A']
Common Mistakes
- Assuming
where()returns Models, not plain objects.where()returns an array of Model references. You can still call.get()on them. - Using Underscore methods like
_.filter(collection, ...)instead ofcollection.filter(...). Both work, but the collection method is cleaner and preserves the collection context. - Forgetting
.value()at the end of achain(). Chain returns a wrapped object. Call.value()to unwrap the result. - Modifying the array returned by
where(). The returned array is a live reference. Mutating it can affect the Collection. Clone with_.clone()if needed. - Using
sortBy()to permanently reorder.sortBy()returns a new array. Setcomparatoron the Collection for permanent ordering.
Practice Questions
- What is the difference between
where()andfindWhere()? - How do you extract all values of a specific attribute from a Collection?
- What does
chain()return and how do you get the final result? - How is
filter()different fromwhere()? - Challenge: Create a Collection of
ProductModels (name, price, category, inStock). Use chain() to filter in-stock products, sort by price ascending, group by category, and pluck the names of the first 3 in each group.
FAQ
Mini Project
Create a LogEntry Collection with fields: timestamp, level, source, message. Add methods: errorsOnly(), bySource(source), recent(minutes), and summary(). Populate with 10 entries and call each method.
What's Next
Now that you can query Collections, learn Backbone Views to render data to the screen. Then study Backbone View Events for handling user interactions.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro