Conditional field selection with Mongoose

mongodb, mongoose

Solution

No, there's not anyway in MongoDb currently to in one query to selectively return different sets of fields depending on conditions. A query in MongoDb and the associated projection applies to all documents.

A map reduce cannot do this (as a map reduce needs to return the same values for each document) and would be a poor fit. An aggregation isn't a general purpose alternative to many queries and returning fields conditionally would be complex.

You have a few options:

- Execute multiple queries and merge the results. That would be very simple as each result is an array, so you could just merge the arrays.

- Return the superset of all fields and filter in your app code.

I'd test the performance of the options. Neither are complex.

Problem

Say I have a collection of users with usernames and email addresses. ``` { name: 'John Doe', email: 'john@doe.com', level: 5 } { name: 'Fred Foo', email: 'fred@foo.com', level: 2 } { name: 'Jo Green', email: 'jo@green.com', level: 5 } { name: 'Paul Bar', email: 'paul@bar.com', level: 3 } ``` I want to query this collection, selecting all users' names and levels. In Mongoose, I could do that like this: ``` User .find() .select('name level') .exec(callback) ``` This would give me the following: ``` { name: 'John Doe', level: 5 } { name: 'Fred Foo', level: 2 } { name: 'Jo Green', level: 5 } { name: 'Paul Bar', level: 3 } ``` But if a user's level is above 4, I want to also get their email address. This would give me the following: ``` { name: 'John Doe', email: 'john@doe.com', level: 5 } { name: 'Fred Foo', level: 2 } { name: 'Jo Green', email: 'paul@bar.com', level: 5 } { name: 'Paul Bar', level: 3 } ``` What is the best that with Mongo[ose]?

Original source