Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to populate in mongoose only if ref is not null - not working

I'm trying to get a list of books with their author information.

Some users were deleted and therefore they have not longer a document in the db, therefore, their info is null.

I'm trying to pull books ONLY if their creators still exist.

This is my code:

  Book.find({_creator:{$ne:null}}).populate(
        {
            path: '_creator',
            match: { _id: { $ne: null }}
        })
        .exec(function (err,books) {
        if(err) throw err;
        if(books) {
            res.send(books)
        }
    })

This is what it returns:

  [
    {
        "_id":"55d98e6a4de71010099c59eb",
        "dateOfCreation":"2015-08-23T09:12:10.095Z",
        "_creator":null,
        "__v":0,
        "coverUrl":"cover14403211323926quv.png",
        "description":"asdasd",
        "name":"asdasd"
    }
]

Notice that the _creator field IS null. Why is that?

like image 950
Michael Seltenreich Avatar asked Aug 23 '15 09:08

Michael Seltenreich


1 Answers

you need to understand the order of execution of your code:

  1. mongoose gets all books from the database where {_creator:{$ne:null}}. Mongo is only looking at the reference inside the books collection to determine which documents to return. Your book still has a reference to an author, and mongo will not notice that there is no matching Author in the Authors collection, so your book is loaded.

  2. mongoose is populating all returned results: so it is loading the authors from the Authors collection and replaces the references with the real objects. For your book it does not find a matching author, so it puts the null there.

Thats why you end up with your resultlist.

Mongo does not support joins - therefore you cannot do a query that includes data from more than one collection. Populate is just a way to replace references in your resultlist with real data, you can never use populated data as part of your where clauses.

To solve your issue you can either:

  • filter your final resultlist in JS code, e.g. with _.filter of the lodash library.
  • update all your books and remove the reference whenever you delete an author. You can use hooks on the Author-Schema to do this.

AuthorSchema.post('remove', function(doc) {// update your books here});

like image 131
Reto Avatar answered Nov 24 '22 02:11

Reto