3

I was wondering if this is possible, or do I need to use the aggregation pipeline instead?

I have read posts such as this, and intuitively feel like it's possible.

Example of docs:

{
    "_id": ObjectID("5143ddf3bcf1bfab37d9c6f"),
    "permalink": "btxcacmbqkxbpgtpeero",
    "author": "machine",
    "title": "Declaration of Independence",
    "tags": [
            "study",
            "law"
    ],
    "comments": [
                  {
                    "body": "comment 1",
                    "email": "email_1@test.com",
                    "author": "machine_1"
                   },
                  {
                    "body": "comment 2",
                    "email": "email_2@test.com",
                    "author": "machine_2"
                   },
                  {
                    "body": "comment 3",
                    "email": "email_3@test.com",
                    "author": "machine_3"
                   },
    ]
    "date": ISODate("2013-03-16T02:50:27.878Z")
}

I am trying to access a particular comment in "comments" by it's index position using dot notation in the projection field, with the following:

db.collection.find({permalink: "btxcacmbqkxbpgtpeero"}, {'comments.0.1.': 1})

Where comments.0 is the first item in the field: the array, and .1 is the second comment in the array.

The result I am getting:

{ "_id" : ObjectID("5143ddf3bcf1bfab37d9c6f"), "comments" : [ {  }, {  }, {  } ] }

If I take away the .1, leaving just comments.0, I get the same result:

{ "_id" : ObjectID("5143ddf3bcf1bfab37d9c6f"), "comments" : [ {  }, {  }, {  } ] }

If I take away the .0, leaving just comments, I get the comments still inside their array:

[
   {
    "body": "comment 1",
    "email": "email_1@test.com",
    "author": "machine_1"
   },
   {
     "body": "comment 2",
     "email": "email_2@test.com",
     "author": "machine_2"
   },
   {
     "body": "comment 3",
     "email": "email_3@test.com",
     "author": "machine_3"
   }
]

Can this be done? If so, how?

Machavity
  • 30,841
  • 27
  • 92
  • 100
Jake Stokes
  • 445
  • 1
  • 5
  • 17
  • 1
    Possible duplicate of [MongoDB : use $ positional operator for querying](http://stackoverflow.com/questions/6280259/mongodb-use-positional-operator-for-querying) – Neo-coder Nov 26 '16 at 17:23
  • @Yogesh Not quite; that post is focused on using the [$ operator](https://docs.mongodb.com/v3.2/reference/operator/update/positional/#definition). I am trying to explicitly specify the position with the index of the element. *"The positional $ operator identifies an element in an array to update **without explicitly specifying the position** of the element in the array".* Also I'm querying, and using this in the projection field, whereas the docs seem to say the $ operator is for updates. – Jake Stokes Nov 27 '16 at 14:28
  • For this you should try **[$arrayElement](https://docs.mongodb.com/manual/reference/operator/aggregation/arrayElemAt/)** or **[$slice](https://docs.mongodb.com/v3.2/reference/operator/projection/slice/)** – Neo-coder Nov 27 '16 at 14:38

1 Answers1

3

without aggregation:

db.collection.find({
   permalink:"btxcacmbqkxbpgtpeero"
},
{
   comments:{
      $slice:[
         0,
         1
      ]
   }
})

returns

{
   "_id":ObjectId("583af24824168f5cc566e1e9"),
   "permalink":"btxcacmbqkxbpgtpeero",
   "author":"machine",
   "title":"Declaration of Independence",
   "tags":[
      "study",
      "law"
   ],
   "comments":[
      {
         "body":"comment 1",
         "email":"email_1@test.com",
         "author":"machine_1"
      }
   ]
}

try it online: mongoplayground.net/p/LGbVWPyVkFk

with aggregation:

db.collection.aggregate([
   {
      $match:{
         permalink:"btxcacmbqkxbpgtpeero"
      }
   },
   {
      $project:{
         comment:{
            $arrayElemAt:[
               "$comments",
               0
            ]
         }
      }
   }
])

returns

{
   "_id":ObjectId("583af24824168f5cc566e1e9"),
   "comment":{
      "body":"comment 1",
      "email":"email_1@test.com",
      "author":"machine_1"
   }
}
felix
  • 9,007
  • 7
  • 41
  • 62