corvid
corvid

Reputation: 11187

Unexpected result when trying to filter fields in mongo db

I have a document structured as follows:

{
  _id: "someid",
  games: [{
    slug: "world-of-warcraft",
    class: 'shaman'
  }, {
    slug: 'starcraft-ii',
    class: 'zerg'
  }],
  roles: {
    'starcraft-ii': ['player'],
    'world-of-warcraft': ['player']
  }
}

I am trying to filter it so that only starcraft-ii within the games array will show up for all players in the role of player in starcraft-ii. I do the following:

function getUsersInGame(slug) {
  return Users.find({
    'games.slug': slug,
    [`roles.${slug}`]: 'player'
  }, {
    fields: {
      'games.$': 1,
      'roles': 1
    }
  });
}

However, this does not match within the games array, and instead returns a 1-element array with world-of-warcraft instead.

What is the appropriate way to filter this array in mongo?

Upvotes: 0

Views: 71

Answers (1)

Pio
Pio

Reputation: 4062

Use $elemMatch in your fields, since the $ will return the first element of the array. So your query should look like this:

function getUsersInGame(slug) {
   return Users.find(
    {
      '"roles.'+ slug + '"': { $in : ['player']}
    }, 
    {
      'games': {
          $elemMatch: {'slug': slug}
      },
      'roles': 1
    });

Please note the difference from the docs:

"The $ operator projects the array elements based on some condition from the query statement.

The $elemMatch projection operator takes an explicit condition argument. This allows you to project based on a condition not in the query..."

Upvotes: 1

Related Questions