2

I'm trying to match the emailAddress field and the page_slug. Currently I'm using the following which matches just the about page in the modularSequence:

db.getCollection('users').find({"modularSequence.page_slug": "about"}, {"modularSequence.$": 1 })

This works and returns:

{
    "_id" : ObjectId("5740c631742da6e83389abb4"),
    "modularSequence" : [ 
        {
            "page_id" : "1",
            "sequence" : "m_1",
            "category" : "headers",
            "page_slug" : "about"
        }
    ]
}

Which it half what I want. I'm looking to return the emailAddress field as well. I've tried using this but it returns everything and multiple modular elements:

db.getCollection('users').find({$and:[{"emailAddress": 'paul@example.com'}, {"modularSequence.page_slug": "about"}, {"modularSequence": {$elemMatch: {page_slug:'about'}}}]})

[
  {
    "emailAddress": "paul@example.com",
    "modularSequence": [
      {
        "page_slug": "about",
        "category": "headers",
        "sequence": "m_1",
        "page_id": "1"
      },
      {
        "page_slug": "contact",
        "category": "content",
        "sequence": "m_4",
        "page_id": "2"
      }
    ]
  }
]

How do I match both the emailAddress field and the modularSequence.page_slug - only return a result if both the email address matches and the page_slug?

DennisTurn
  • 139
  • 2
  • 12

1 Answers1

2

Your $and array is including your field selection parameter as well. But you don't need to use $and here anyway as multiple query terms are implicitly ANDed by default, so you can simplify your query to:

db.users.find({"emailAddress": 'paul@example.com', "modularSequence.page_slug": "about"},
              {"emailAddress": 1, "modularSequence.$": 1})

Which is your first query, but with an emailAddress field added to both the query and field selection parameters.

The first parameter of find is the query (which docs), and the second is the projection (which fields within those docs), so that's why those fields are there twice. The $ in the projection represents the modularSequence array element matched in the query.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • That's perfect, thank you very much. A few questions just so I fully understand what's going on as opposed to just C&P'in this. I'm guessing the "emailAddress": 1 is specifying we want the emailAddress from the top level, and "modularSequence.$": 1 - is doing the same but for $ to represent page_slug. The one thing I don't quite understand is why we are specifying emailAddress & modularSequence twice? – DennisTurn Jun 29 '16 at 14:38
  • The first parameter of [`find`](https://docs.mongodb.com/manual/reference/method/db.collection.find/#db.collection.find) is the query (which docs), and the second is the projection (which fields within those docs), so that's why those fields are there twice. The `$` in the projection represents the `modularSequence` array element matched in the query. – JohnnyHK Jun 29 '16 at 14:42
  • One last @JohnnyHK, if I was to allow for multiple occurrences of 'about' within the objects, how would I allow for this? – DennisTurn Jun 29 '16 at 15:00
  • @DennisTurn That's a trickier case. See http://stackoverflow.com/a/12241930/1259510 – JohnnyHK Jun 29 '16 at 15:07