grapher icon indicating copy to clipboard operation
grapher copied to clipboard

Native Hypernova using $lookup in MongoDB 3.6

Open theodorDiaconu opened this issue 7 years ago • 11 comments

MongoDB 3.6 supports nesting and chaining $lookups. As soon as 3.6 gets released this is absolutely crucial to have. And allow both hypernova/aggregate lookup queries.

theodorDiaconu avatar Nov 24 '17 07:11 theodorDiaconu

https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#pipe._S_lookup

theodorDiaconu avatar Dec 06 '17 13:12 theodorDiaconu

I am shocked to discover that hypernova is 10x slower than Grapher for example:

db.getCollection('users').aggregate([
    {
        $project: { _id: 1 }
    },
    {
        $lookup: {
            from: "posts",
            as: "posts",
            let: { id: "$_id" },
            pipeline: [
                {
                    $project: { _id: 1, ownerId: 1 }
                },
                {
                    $match: {
                        $expr: {
                            $eq: ["$ownerId", "$$id"]
                        }
                    },
                },
                {
                    $lookup: {
                        from: 'comments',
                        as: 'comments',
                        let: { id: "$_id"},
                        pipeline: [
                            {
                                $project: { _id: 1, postId: 1 }
                            },
                            {
                                $match: {
                                   $expr: {
                                       $eq: ["$postId", "$$id"]
                                   }
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
]);

Takes 400ms. With Grapher it takes 19-23ms.

theodorDiaconu avatar Dec 06 '17 14:12 theodorDiaconu

Could it be that it's not using indexes?

Herteby avatar Dec 06 '17 14:12 Herteby

It's the same db, I've set it up locally. Why wouldn't it use index, $match should be smart enough maybe?

theodorDiaconu avatar Dec 06 '17 14:12 theodorDiaconu

yes $lookup is very slow

crapthings avatar Jan 23 '18 01:01 crapthings

Currently, new $lookup (3.6 version) is not using indexes.

New $lookup version (MongoDB >= 3.6)

db.getCollection('users').aggregate([
    {
        $project: { _id: 1 }
    },
    {
        $lookup: {
            from: 'posts',
            as: 'posts',
            let: { id: '$_id' },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq: ['$ownerId', '$$id']
                        }
                    },
                }
            ]
        }
    }
]);

Old $lookup version (MongoDB < 3.6)

db.getCollection('users').aggregate([
    {
        $project: { _id: 1 }
    },
    {
        $lookup: {
            from: 'posts',
            as: 'posts',
            localField: '_id',
            foreignField: 'ownerId'
        }
    }
]);

Last query uses indexes, the other one not

davidbayo10 avatar Jun 02 '18 16:06 davidbayo10

Ok, so how would you run that whole query with that approach?

Regards, Theodor

On 2 Jun 2018, at 9:46 AM, David Bayo Alcaide [email protected] wrote:

Currently, new $lookup (3.6 version) is not using indexes.

New $lookup version (MongoDB >= 3.6)

db.getCollection('users').aggregate([ { $project: { _id: 1 } }, { $lookup: { from: 'posts', as: 'posts', let: { id: '$_id' }, pipeline: [ { $match: { $expr: { $eq: ['$ownerId', '$$id'] } }, } ] } } ]); Old $lookup version (MongoDB < 3.6)

db.getCollection('users').aggregate([ { $project: { _id: 1 } }, { $lookup: { from: 'posts', as: 'posts', localField: '_id', foreignField: 'ownerId' } } ]); Last query uses indexes, the other one not

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

theodorDiaconu avatar Jun 02 '18 16:06 theodorDiaconu

With that approach it is difficult to solve that case, because you need a deep lookup. I think MongoDB should fix indexes problem in last $lookup version and your query will work perfectly.

davidbayo10 avatar Jun 06 '18 06:06 davidbayo10

@davidbayo10 then it's irrelevant what you showed me. Another huge problem of $lookup is that it does not work with sharded collection, Grapher works with sharded collections.

theodorDiaconu avatar Jun 06 '18 07:06 theodorDiaconu

I just showed you two examples of $lookup. First one not uses indexes and the second one yes. But your first query is slow because of MongoDB issue with new $lookup version

davidbayo10 avatar Jun 06 '18 07:06 davidbayo10

@davidbayo10 look here: https://docs.mongodb.com/manual/core/aggregation-pipeline/#aggregation-pipeline-operators-and-performance

It seems that if we apply projection after $match then it may work ? This is confusing a bit. Why would having $projection first disable the ability to use indexes, or maybe indexes can't be used when having $match with $expr

theodorDiaconu avatar Jun 06 '18 07:06 theodorDiaconu