Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why MongoDB $elemMatch returns all elements in array?

In mongoDB (2.4) I have collection students with bunch of documents in it. Each document will have structure as below:

{
    "_id" : ObjectId("55f16640a17eed480bb0dc18"),
    "messages" : [
        {
            "_id" : ObjectId("55fc60bc260c9be5879ef733"),
            "createdOn" : ISODate("2015-09-18T19:06:36.793Z"),
            "fromUser" : ObjectId("55f16a6af9c703280c5b2c0e"),
            "toUser" : ObjectId("55f16640a17eed480bb0dc18"),
            "type" : 1
        },
        {
            "_id" : ObjectId("55fc6d200d6097e98b210bff"),
            "createdOn" : ISODate("2015-09-18T19:59:28.439Z"),
            "fromUser" : ObjectId("55f721d1e1242e7c4c129471"),
            "toUser" : ObjectId("55f16640a17eed480bb0dc18"),
            "type" : 1
        }
    ]
}

Now, I need to pull out one of the subdocuments from messages array, say with messages._id equal 55fc60bc260c9be5879ef733 so I use $elemMatch:

db.users.find({"_id": new ObjectId('55f16640a17eed480bb0dc18'),
                "messages": {
                    $elemMatch:{
                        "_id": new ObjectId('55fc60bc260c9be5879ef733'),
                        "fromUser": new ObjectId('55f16a6af9c703280c5b2c0e'),
                        "toUser": new ObjectId('55f16640a17eed480bb0dc18'),
                        "type": 1

                }}}).pretty();

But this gives me:

{
    "_id" : ObjectId("55f16640a17eed480bb0dc18"),
    "messages" : [
        {
            "_id" : ObjectId("55fc60bc260c9be5879ef733"),
            "createdOn" : ISODate("2015-09-18T19:06:36.793Z"),
            "fromUser" : ObjectId("55f16a6af9c703280c5b2c0e"),
            "toUser" : ObjectId("55f16640a17eed480bb0dc18"),
            "type" : 1
        },
        {
            "_id" : ObjectId("55fc6d200d6097e98b210bff"),
            "createdOn" : ISODate("2015-09-18T19:59:28.439Z"),
            "fromUser" : ObjectId("55f721d1e1242e7c4c129471"),
            "toUser" : ObjectId("55f16640a17eed480bb0dc18"),
            "type" : 1
        }
    ]
}

If I understand docs correctly http://docs.mongodb.org/v2.4/reference/operator/projection/elemMatch/ I should receive only:

{
    "_id" : ObjectId("55f16640a17eed480bb0dc18"),
    "messages" : [
        {
            "_id" : ObjectId("55fc60bc260c9be5879ef733"),
            "createdOn" : ISODate("2015-09-18T19:06:36.793Z"),
            "fromUser" : ObjectId("55f16a6af9c703280c5b2c0e"),
            "toUser" : ObjectId("55f16640a17eed480bb0dc18"),
            "type" : 1
        }
    ]
}

So what am I doing wrong?

like image 897
spirytus Avatar asked Sep 06 '25 15:09

spirytus


1 Answers

You are not using the projection operator $elemMatch match, but the query operator $elemMatch

In other words, you don't project anything, but use $elemMatch for filtering the results that your query should return.

In order for your projection to work, you should change your query to something like:

db.users.find(
    {"_id": new ObjectId('55f16640a17eed480bb0dc18')},
    {"messages": {$elemMatch:{"_id": new ObjectId('55fc60bc260c9be5879ef733')}}}
).pretty();

The above query should return the _id field (same as appears in the query clause), and the array element whose id is mentioned in the projection clause

like image 190
Ori Dar Avatar answered Sep 09 '25 00:09

Ori Dar