Skip to content

Backbone Collection Methods — Filtering, Sorting, and Querying Data

DodaTech Updated 2026-06-28 6 min read

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

  1. Assuming where() returns Models, not plain objects. where() returns an array of Model references. You can still call .get() on them.
  2. Using Underscore methods like _.filter(collection, ...) instead of collection.filter(...). Both work, but the collection method is cleaner and preserves the collection context.
  3. Forgetting .value() at the end of a chain(). Chain returns a wrapped object. Call .value() to unwrap the result.
  4. Modifying the array returned by where(). The returned array is a live reference. Mutating it can affect the Collection. Clone with _.clone() if needed.
  5. Using sortBy() to permanently reorder. sortBy() returns a new array. Set comparator on the Collection for permanent ordering.

Practice Questions

  1. What is the difference between where() and findWhere()?
  2. How do you extract all values of a specific attribute from a Collection?
  3. What does chain() return and how do you get the final result?
  4. How is filter() different from where()?
  5. Challenge: Create a Collection of Product Models (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

Do Collection methods mutate the original Collection?

Most methods like filter, sortBy, groupBy return new arrays. The Collection is not modified.

Can I use native Array methods on a Collection?

Collections are not arrays, but they have a models array. You can call collection.models.filter(...) with native methods.

What is the performance of `where()` on large collections?

where() iterates all models. For 10K+ items, consider indexing or server-side filtering.

Are Collection methods chainable?

Yes, use collection.chain() for full chaining support from Underscore.

Can I add custom collection methods?

Yes. Define them in the extend object. They become instance methods.

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