Jimi
Jimi

Reputation: 1845

How to efficiently query complex hierarchy on MongoDB

Let's say you have two collections: CollectionA and CollectionB.

In CollectionA you have a document model like this

_id
childs{
   kind
   position
   childA
   childB
}

With childA being a reference to a document in the CollectionA, and childB being a reference to a document in CollectionB

In CollectionB you have a document model like this

_id
propertyA
propertyB

What I've done in Node.Js is a recursive function like in this pseudocode

function getProperties(id){
    let properties = [];
    if(id) {
        let document = collectionB.findOne(id);
        if(document && document.childs) {
            for(let child of document.childs) {
                if(child.childB){
                    properties = properties.concat(getProperties(child.childB)):
                }
                if(child.childA){
                    let documentA = collectionA.findOne(child.childA);
                    if(documentA){
                        properties.push(documentA.prpertyA);
                    }
                }
            }
        }
    }
    return properties;
}

However, as childs grows, the time to get all the properties from the hierarchy grows as well, sometimes leading to a minute of waiting time (or even timeouts in some cases!). So, how can I improve this, maybe using some mongodb native functions? I'm already using DataLoader inside the findOne functions, which helped but not as much as I thought.

Upvotes: 0

Views: 301

Answers (1)

thangavel .R
thangavel .R

Reputation: 466

You can use aggregate to create complex queries in a simple way.

For your example, you have two collections: Collection A, Collection B

Your base collection is B, so we can create an aggregate pipeline from collection B

db.collectionB.aggregate([
{
    $match: { _id: id } //
},
{
    $lookup:
    {
        from: 'collectionB',
        localField: '_id',
        foreignField: 'childB',
        as: 'childBobj'
    }
}
{
    $lookup:
    {
        from: 'collectionA',
        localField: '_id',
        foreignField: 'childA',
        as: 'childAobj'
    }
}
])

The query is not completely satisify your goal, Please make changes accordingly.

And I highly reccommended you to take a look at db.collection.aggregate

And even you can use indexing to make this query execution time faster.

Happy coding!.

Upvotes: 1

Related Questions