Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a subset of array items in MongoDB

Can anyone offer advice on how I would return a subset of array items? For example, let's suppose I have a collection of documents (similar to the example below) that contains a simple _id key and a key that contains an array of objects.

I would like to find all _id's and the matching objects that match a simple criteria:

// campaigns
{
  "_id" : "Fred's C25K",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "nike"
    },
    {
      "date" : "2015-06-17",
      "source" : "reebok",
    },
    {
      "date" : "2015-06-12",
      "source" : "nike"
    },
    {
      "date" : "2015-06-14",
      "source" : "adidas"
    },
  ]
},
{
  "_id" : "Mike's Marathon",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "nike"
    }
  ]
},
{
  "_id" : "Jacob's Jamboree",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "keen"
    }
  ]
}

I would like my result to contain the _id and any matching objects for, say, a date value of "2015-06-17"

// GOAL => To generate a result set that looks like:
{
  "_id" : "Fred's C25K",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "nike"
    },
    {
      "date" : "2015-06-17",
      "source" : "reebok",
    }
  ]
},
{
  "_id" : "Mike's Marathon",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "nike"
    }
  ]
},
{
  "_id" : "Jacob's Jamboree",
  "campaignData" : [
    {
      "date" : "2015-06-17",
      "source" : "keen"
    }
  ]
}
like image 598
R Brennan Avatar asked Jun 19 '15 16:06

R Brennan


People also ask

How do you get a specific object from an array in MongoDB?

To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.

How do I slice a string in MongoDB?

Divides a string into an array of substrings based on a delimiter. $split removes the delimiter and returns the resulting substrings as elements of an array. If the delimiter is not found in the string, $split returns the original string as the only element of an array. The string to be split.

What does $Push do in MongoDB?

Description. In MongoDB, the $push operator is used to appends a specified value to an array. If the mentioned field is absent in the document to update, the $push operator add it as a new field and includes mentioned value as its element.

What is $slice in MongoDB?

In MongoDB, the $slice operator decide the retrieval of a number of items of an array that a query returns. The $slice accepts a number including a negative number as an argument and returns the output.


1 Answers

Use the aggregation framework to achieve the desired result. The following pipeline consists of a $match operator stage as the first step to filter the documents that should pass through the pipeline.

The next stage is the $addFields operator that allows you to output documents that contain all existing fields from the input documents and newly added fields.

Within this step you can use the $filter operator to select a subset of an array to return based on the specified filter:

db.collection.aggregate([
    { "$match": {
        "campaignData.date" : "2015-06-17"
    } },
    { "$addFields": {
        "campaignData": {
            "$filter": {
                "input": "$campaignData",
                "cond": {
                    "$eq": ["$$this.date", "2015-06-17"]
                }
            }
        }
    } }
])

Result:

/* 0 */
{
    "result" : [ 
        {
            "_id" : "Mike's Marathon",
            "campaignData" : [ 
                {
                    "date" : "2015-06-17",
                    "source" : "nike"
                }
            ]
        }, 
        {
            "_id" : "Jacob's Jamboree",
            "campaignData" : [ 
                {
                    "date" : "2015-06-17",
                    "source" : "keen"
                }
            ]
        }, 
        {
            "_id" : "Fred's C25K",
            "campaignData" : [ 
                {
                    "date" : "2015-06-17",
                    "source" : "nike"
                }, 
                {
                    "date" : "2015-06-17",
                    "source" : "reebok"
                }
            ]
        }
    ],
    "ok" : 1
} 
like image 78
chridam Avatar answered Sep 24 '22 20:09

chridam