0

I am trying to export a list of all the Reference child nodes with the attribute input. There are about 1000 documents in the collection. The desired output would be a find() query that only outputs the contents of the Reference field within the Tag field.

For example:

{
        "_id" : ObjectId("5dfb7189986b7c30f33987c3"),
        "Tag" : [
                {
                        "attribute" : "input",
                        "Reference" : "product"
                },
                {
                        "attribute" : "more",
                        "Reference" : "extra"
                }
        ]
}

Output: [product]

My query at the moment:

db.test.find(
    {$and :
    [
        { "Tag.attribute":"input"},
        {"Tag.attribute": { $ne:null}}
    ]}
    ,{_id:0,"Tag.Reference":"1"}).pretty()

Returns: [product,extra]

Any help would be appreciated, Thanks.

Kingswoop
  • 148
  • 8

2 Answers2

1

Assuming you want to extract the first Reference from the Tag attribute.

You can use the aggregation pipeline to achieve this.

Prepare Data:

db.collection.insertMany([{
        "Tag" : [
                {
                        "attribute" : "input",
                        "Reference" : "product2"
                },
                {
                        "attribute" : "more",
                        "Reference" : "extra"
                }
        ]
},
{
        "Tag" : [
                {
                        "attribute" : "input",
                        "Reference" : "product1"
                },
                {
                        "attribute" : "more",
                        "Reference" : "extra"
                }
        ]
}])

Aggergation Framework:

db.collection.aggregate([
    {
        $group :{
            _id:null,
            reference :{$push : {$arrayElemAt: ["$Tag.Reference", 0]}}
        }
    }
    ])

Output:

{
    "_id" : 0,
    "reference" : [
        "product2",
        "product1"
    ]
}
Anurag Wagh
  • 1,086
  • 6
  • 16
0

What you want may be a filter as part of an aggregation.

This question gives some interesting solutions: Retrieve only the queried element in an object array in MongoDB collection

Based on that I learnt that a filter can pull out the relevant items in the array.

The steps for your problem could be:

  1. your match statement

  2. a projection with a filter to get just the right array elements

  3. another projection or grouping to get only the data you want

So this should get you the data in MongoDB 3.2+.

db.test.aggregate([
   {$match: { "Tag.attribute":"input"}},
   {$project: {"Tag": 
        {$filter: {input: '$Tag', as: 'item',cond: {$eq: ['$$item.attribute', 'input']}}}}},
    {$project:{"Tag.Reference":1,_id:0}}])

Output

{ "Tag" : [ { "Reference" : "product" } ] }

Note: with the dummy data provided the initial match is not needed.

To see the filter step in isolation try this:

db.test.aggregate([       
    {$project: 
    {"Tag":          
        {$filter: {input: '$Tag', as: 'item',cond: {$eq: ['$$item.attribute', 'input']}}}
}}])
shift
  • 76
  • 4