0

I am using mongoose with nodejs express framework

Here is the document in mongo :

{                                                                        
        "_id" : ObjectId("59c1fe16b68d844d8473c6fe"),                    
        "is_active" : "0",                                               
        "membership_expiry_date" : ISODate("2018-09-20T05:35:18.485Z"),  
        "date_of_joining" : ISODate("2017-09-20T05:35:18.485Z"),         
        "user_name" : "Max M",                                         
        "first_name" : "Max",                                          
        "password" : "MyPwd",                                            
        "address" : "NewTown",                                         
        "email_id" : "max@gmail.com",                                    
        "phone_number" : "12345678901",                                    
        "books_borrowed" : [                                             
                {                                                        
                        "due_date" : ISODate("2017-09-22T05:35:18.511Z"),
                        "book_id" : "1234",                              
                        "is_renewed" : true,                             
                        "_id" : ObjectId("59c1fe16b68d844d8473c700")     
                },                                                       
                {                                                        
                        "due_date" : ISODate("2017-09-22T05:35:18.531Z"),
                        "book_id" : "1235",                              
                        "is_renewed" : false,                            
                        "_id" : ObjectId("59c1fe16b68d844d8473c6ff")     
                }                                                        
        ],                                                               
        "__v" : 0                                                        
}       

Now when I try to access books_borrowed where user_name=Max and book_id=1234 I am using

model.findOne({"user_name":"Max M","book_id":1234}, {
        'books_borrowed': 1
    },
    function(err, res) {
        console.log("##Err:: " + JSON.stringify(err) + " response:: " + JSON.stringify(res));
        if (err) {
            return callback('Error while updating...');
        } else {
            return callback(null, res);
        }
    });

This returns error = null and response is also null.

If I replace book_id by 'books_borrowed.book_id' then I get

{
  "_id": "59c1fe16b68d844d8473c6fe",
  "books_borrowed": [
    {
      "due_date": "2017-09-22T05:35:18.511Z",
      "book_id": "1234",
      "is_renewed": true,
      "_id": "59c1fe16b68d844d8473c700"
    },
    {
      "due_date": "2017-09-22T05:35:18.531Z",
      "book_id": "1235",
      "is_renewed": false,
      "_id": "59c1fe16b68d844d8473c6ff"
    }
  ]
}

Which also contains data with book_id = 1235.

I just want object containing data with book_id=1234.

What am I missing here ? Also I don't want those object ids being inserted in my books_borrowed object.

TGW
  • 805
  • 10
  • 27

3 Answers3

0

You cannot make a call to book_id directly in the query as it is not there in the main document. You need to get all the borrowedBooks and then filter the "books_borrowed" to get the required document.

model.findOne({"user_name":"Max M","books_borrowed":{$elemMatch:{"book_id":"1234"}}, {
    'books_borrowed': 1
},
function(err, res) {
    // Your code here
});
Shubham Jain
  • 930
  • 1
  • 14
  • 24
  • agree, use `$elemMatch` but careful the `book_id` were in `String` not `Int` – Ryan Harne Sep 20 '17 at 07:13
  • Well this gives me null in error as well as response – TGW Sep 20 '17 at 07:14
  • I have put logs in callback this is what I am getting: err:: null res:: null, As Ryan mentioned I tried it as string too, but still same Sorry my bad I used incorrect name, but still it is giving me all elements inside books_borrowed array. – TGW Sep 20 '17 at 07:18
  • Check your secondary args; `{'books_borrowed': 1}`... this alone is working `model.findOne({"user_name":"Max M","books_borrowed":{$elemMatch:{"book_id":"1234"}}});` – Ryan Harne Sep 20 '17 at 07:19
  • Remove {'books_borrowed': 1} and see what is the result. – Shubham Jain Sep 20 '17 at 07:22
  • Yes but in any case what I want is only object whose book_id is 1234, but what I am getting is both objects that is book_id=1234 as well as one with id=12345, in case I remove secondary argument {'books_borrowed': 1}, I get whole doc. Removing it only gives whole do the conditions are still don't seem to get executed. – TGW Sep 20 '17 at 07:26
  • 1
    I have edited my answer. The type of book_id was String and not int. Try now – Shubham Jain Sep 20 '17 at 07:27
  • Yes Shubham I tried that not working – TGW Sep 20 '17 at 07:28
  • Still sending null? – Shubham Jain Sep 20 '17 at 07:29
  • Seems I had to use filter as Ryan mentioned in his answer, thanks for the help buddy :) – TGW Sep 20 '17 at 07:45
0

You can't access book_id directly as it is inside an array. Try this:

model.findOne({"user_name":"Max M", books_borrowed: {$elemMatch: {book_id:'1234'}}})
prisoner_of_azkaban
  • 700
  • 1
  • 8
  • 26
  • As I mentioned already in my question, If I replace book_id by 'books_borrowed.book_id' then I get { "_id": "59c1fe16b68d844d8473c6fe", "books_borrowed": [ { "due_date": "2017-09-22T05:35:18.511Z", "book_id": "1234", "is_renewed": true, "_id": "59c1fe16b68d844d8473c700" }, { "due_date": "2017-09-22T05:35:18.531Z", "book_id": "1235", "is_renewed": false, "_id": "59c1fe16b68d844d8473c6ff" } ] } Which returns everything inside array. – TGW Sep 20 '17 at 07:14
  • @TGW updated the answer you don't need second argument btw. – prisoner_of_azkaban Sep 20 '17 at 07:19
  • Thanks but that didn't help either, so going with Ryan's answer :) – TGW Sep 20 '17 at 07:46
0

Use this to filter the books_borrowed result

model.findOne({
    "user_name":"Max M",
    "books_borrowed": {
        $elemMatch: {"book_id": "1234"}
    }
}, 
{
    "user_name": 1,
    // ... as needed 
    "books_borrowed.$": 1
});
Ryan Harne
  • 469
  • 3
  • 7
  • this is under Projection / Positional: https://docs.mongodb.com/manual/reference/operator/projection/positional/#proj._S_ – Ryan Harne Sep 20 '17 at 07:35
  • Thanks Ryan this worked, I would like to know more about that .$ filter I am new to mongo and mongoose as well. Edit:: I missed your comment with link thanks :) – TGW Sep 20 '17 at 07:38
  • Ahh so the issue was in projection I didn't added "user_name": 1 :) – Shubham Jain Sep 20 '17 at 07:50
  • no, see given `Max M` data, there are 2 `books_borrowed`.. @TGW just want a filtered result; just show one as queried. :-) – Ryan Harne Sep 20 '17 at 07:52