Ali Kleit
Ali Kleit

Reputation: 3659

MongoDb: Project an element's property inside an array in a document with conditions

I have the following array of collection of books. I'm trying to project a single property of an element in an array.

My query is projecting the text property in comments array for book of year 2012 for author A1.

Example books array:

[
    {
        book_id: "1",
        title:'B1',
        year: 2012,
        comments: [
            {
                author: "A1",
                text: "C1"
            }
        ]
    },
    {
        book_id: "2",
        title:'B2',
        year: 2012,
        comments: [
            {
                author: "A2",
                text: "C2.0"
            },
            {
                author: "A1",
                text: "C2.1"
            },
            {
                author: "A1",
                text: "C2.2"
            },

        ]
    },
    {
        book_id: "3",
        title:'B3',
        year: 2013,
        comments: [
            {
                author: "A1",
                text: "C3"
            }
        ]
    },
]

expected result


[
    "C1",
    "C2.1",
    "C2.2"
]

I tried the following:


// query using find

db.books.find(
{year:2012, comments: {$elemMatch : {author:"A1" } } },{_id:0,'comments.text':1}
)

// results
/* 1 */
{
    "comments" : [ 
        {
            "text" : "C1"
        }
    ]
}

/* 2 */
{
    "comments" : [ 
        {
            "text" : "C2.0"
        }, 
        {
            "text" : "C2.1"
        }, 
        {
            "text" : "C2.2"
        }
    ]
}


// query using aggregation


db.books.aggregate(
[
    {$match: {year:2012}},
    {
        $project:{
            comments: {
                $filter:{
                    input: "$comments",
                    as:'comment',
                    cond: {$eq:['$$comment.author','A1']}
                }
            }

        }
     }
])

// results in

/* 1 */
{
    "_id" : ObjectId("5d3446f9d9eac0ed968aad4b"),
    "comments" : [ 
        {
            "author" : "A1",
            "text" : "C1"
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5d3446f9d9eac0ed968aad4c"),
    "comments" : [ 
        {
            "author" : "A1",
            "text" : "C2.1"
        }, 
        {
            "author" : "A1",
            "text" : "C2.2"
        }
    ]
}



Upvotes: 2

Views: 2228

Answers (1)

Ashh
Ashh

Reputation: 46491

You can use below aggregation

db.collection.aggregate([
  { "$match": { "year": 2012, "comments": { "$elemMatch": { "author": "A1" }}}},
  { "$unwind": "$comments" },
  { "$match": { "year": 2012, "comments.author": "A1" }},
  { "$group": {
    "_id": null,
    "data": { "$push": "$comments.text" }
  }}
])

Output

[
  {
    "_id": null,
    "data": [
      "C1",
      "C2.1",
      "C2.2"
    ]
  }
]

You cannot return simple array string with mongodb because it only returns the BSON document rather than just array of elements.

Upvotes: 4

Related Questions