Skip to content

Instantly share code, notes, and snippets.

@cakriwut
Last active September 10, 2016 02:43
Show Gist options
  • Save cakriwut/50e9dd83e80628ddec961f18e169e16b to your computer and use it in GitHub Desktop.
Save cakriwut/50e9dd83e80628ddec961f18e169e16b to your computer and use it in GitHub Desktop.
How to filter array inside mongoDB document, so it will return a document with filtered array inside.
/* 1 */
{
"_id" : "joe",
"name" : "Joe Bookreader",
"addresses" : [
{
"street" : "123 Fake Street",
"city" : "Faketon",
"state" : "MA",
"zip" : "12345"
},
{
"street" : "1 Some Other Street",
"city" : "Boston",
"state" : "MA",
"zip" : "12345"
}
]
}
/* 2 */
{
"_id" : "driver",
"name" : "Driver X",
"addresses" : [
{
"street" : "123 Fake Street 12222",
"city" : "Faketon",
"state" : "MA",
"zip" : "11111"
},
{
"street" : "1 Some Other Street 34",
"city" : "Boston",
"state" : "MA",
"zip" : "12345"
}
]
}
db.getCollection('sample').aggregate(
{
"$match": {
"addresses.zip" : "11111"
}
},
{
"$unwind" :"$addresses"
},
{
"$match": {
"addresses.zip" : "11111"
}
},
{
"$group" : {
"_id": "$_id",
"addresses" :{
"$addToSet" : "$addresses"
}
}
)
@cakriwut
Copy link
Author

This aggregate functions performs following steps to produce the filtered array:

  1. Step 1 -> Filter the document, where addresses.zip = "11111"
  2. Step 2 -> Pipe the result to $unwind by addresses, where each Document will contains only individual addresses.
  3. Step 3 -> Pipe the result to filter, where addresses.zip = "11111".
  4. Step 4 -> Pipe the result to group based on _id , and reconstruct the $addresses

So what's going on?
To have better understanding, you can remove the pipe process (Step 2-4) and incrementally adding it to the aggregate during your understanding process.

Step 1 - is a filter to document in the collection. The result is all documents where any of zip is "11111". Using sample data, it returns 2 document.
Step 2 - unwind process will extract each individual addresses into different documents. Using sample data, it returns 4 documents. Each document contains single address.
Step 3 - is a filter to document in the in-memory document. These documents now only has single address each - therefore re-applying same filter as Step 1, will remove un-match address from the result.
Step 4 - is a grouping process. In-memory document contains filtered document, with single addresses each - it is also filtered after Step 3 was applied. Grouping will construct original presentation of the document - with filtered array of addresses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment