Text query through referenced objects with MongoDB

47 views Asked by At

I have the following structure.

books collection:

{
    _id: "book_1",
    title: "How to build a house",
    authorId: "author_1"
}

{
    _id: "book_2",
    title: "How to plant a tree",
    authorId: "author_2"
}

authors collection:

{
    _id: "author_1",
    name: "Adam Adamson"
}

{
    _id: "author_2",
    name: "Brent Brentson"
}

I want to make a case insensitive free text search with the string "b" through the books collection and find all books that either has the "b" in the title or has an author with "b" in the name.

I can embed the author in the book object just to be able to make the query. But if the author name changes in the authors collection, the embedded authors object will have the wrong name.

{
    _id: "book_2",
    title: "How to plant a tree",
    authorId: "author_2",
    author:
    {
        name: "Brent Brentson"
    }
}

What would be a good way to solve this problem?

1

There are 1 answers

2
chridam On BEST ANSWER

You could use the following queries where the first gets the array of author ids that match the given regex expression query on the authors collection (using the map() method of the find() cursor) and the second query applies that array in the books collection query using the $in operator as well as using the regex pattern to find books that have "b" in the title:

var authorIds = db.authors.find({"name": /b/i}).map(function (doc) {return doc._id}); 
db.books.find({$or: [{"title": /b/i}, {"authorId": {"$in": authorIds} }]})

Result:

/* 0 */
{
    "_id" : "book_1",
    "title" : "How to build a house",
    "authorId" : "author_1"
}

/* 1 */
{
    "_id" : "book_2",
    "title" : "How to plant a tree",
    "authorId" : "author_2"
}

-- UPDATE --

Thanks to @yogesh for suggesting another approach which uses the distinct() method to get the author ids list:

var authorIds = db.authors.distinct("_id", {"name": /b/i})