0

EDIT: This is my Schema:

{
    "_id": "salfjasdlkfjaslkdfj",
    "data": [
        {
            "title": "data1",
            "_id": "xxx",
            //more fields
        },
        {
            "title": "data2",
            "_id": "yyy",
            //more fields
        },
        {
            "title": "data3",
            "_id": "zzz",
            //more fields
        }
    ],
    //more fields
}

and my query in mongoose looks like this:

mySchema.findOne(
    id,
    {"data": {$elemMatch: {"_id": {$in: ["xxxxx", "yyyyy"]}}}},
    {},
    function(err, data){
        if(err){
            console.log(err);
            res.send(err);
            return;
        }
        res.json(data);
    }
);

I want to project 2 or more elements from the "data" array. However, with this code, the result always contains only one element from "data" even if the array after "$in" has 2 or more elements.

This works perfectly fine without the "$in" (that is, for projecting only one element from the "data" array).

according to https://jira.mongodb.org/browse/SERVER-3544, $elemMatch and $in should work with each other.

  • Is there something wrong with my code?
  • If $elemMatch and $in STILL don't work with each other, is there another way to project this?

EDIT: The expected output is this:

{
    "_id": "salfjasdlkfjaslkdfj",
    "data": [
        {
            "title": "data1",
            "_id": "xxx",
            //more fields
        },
        {
            "title": "data2",
            "_id": "yyy",
            //more fields
        },
    ]
}

I just tried this query but it gives me an empty array! "[ ]". I think I'm messing up the syntax somewhere, or something. I'm not sure.

mySchema.aggregate(
    [
            {$match: {"_id": id}},
            {$unwind: "$data"},
            {$match: {"data._id": {$in: ["xxx", "yyy"]}}},
            {$project: {"data":1}}
    ],
    function(err, data){
        if(err){
            console.log(err);
            res.send(err);
            return;
        }
        res.json(data);
    }
);
Abhijeet Limaye
  • 107
  • 3
  • 8
  • `elemMatch` projects the _first_ element from the array that matches. It will never project multiple elements. See the definition at http://docs.mongodb.org/manual/reference/operator/projection/elemMatch/ – Aaron Dufour Oct 01 '15 at 21:07
  • Oh I see. Is there another way to project multiple elements from the array? @AaronDufour – Abhijeet Limaye Oct 01 '15 at 21:08
  • I don't know, which is why I left a comment and not an answer. I just happened to recognize `elemMatch`. I haven't touched Mongo in awhile. – Aaron Dufour Oct 01 '15 at 21:14
  • Possible duplicate of [Retrieve only the queried element in an object array in MongoDB collection](http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection). All answers mentioning aggregate are how to filter out multiple matches – Blakes Seven Oct 01 '15 at 22:10

1 Answers1

0

Finally I found the problem! The "id" was in a String format and I needed to parse it in the ObjectId() format. This is the working code:

for(var i=0;i<array.length;i++){
    array[i] = mongoose.Types.ObjectId(array[i]);
}

mySchema.aggregate(         
    [
        {$match: {"_id": mongoose.Types.ObjectId(id)}},
        {$unwind: "$data"},
        {$match: {"data._id": {$in: array}}},
        {$group: {"_id": "$_id", "data": { $push: '$data' }}},
        {$project: {"data": 1}}
    ],
    function(err, data){
        if(err){
            console.log(err);
            res.send(err);
            return;
        }
        res.json(data);
    }
);
Abhijeet Limaye
  • 107
  • 3
  • 8