MongoDB 使用聚合框架的条件 $lookup

MongoDB conditional $lookup with aggregration framework

我正在尝试使用聚合框架进行条件查找。在我的本地和国外 collections 我有两个字段:fieldA 和 fieldB。如果 fieldA != 0 我的 $lookup 应该是:

{ from: 'collectionA', localField: 'fieldA', foreignField: 'fieldA', as: 'agg' }

否则,如果 fieldA = 0,我的 $lookup 应该是:

{ from: 'collectionA', localField: 'fieldB', foreignField: 'fieldB', as: 'agg' }

是否可以将这些条件与单个 $lookup 结合起来?

这不太可能 OOB,但您可以通过多种方式解决这个问题。

例如根据这个条件添加一个新的“临时”字段:

db.colleciton.aggregate([
    {
        $lookup: {
            from: 'collectionA',
            let: {
                fieldA: "$fieldA", fieldB: "$fieldB"
            },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq: [
                                {
                                    $cond: [
                                        {
                                            $eq: [
                                                '$$fieldA',
                                                0,
                                            ],
                                        },
                                        '$$fieldB',
                                        '$$fieldA',
                                    ],
                                },
                                {
                                    $cond: [
                                        {
                                            $eq: [
                                                '$$fieldA',
                                                0,
                                            ],
                                        },
                                        '$fieldB',
                                        '$fieldA',
                                    ],
                                }
                            ],
                        },
                    },
                },
            ],
            as: 'agg',
        },
    }
])

这种方法的问题是索引不会用于查找旧的 Mongo 版本,这在某些情况下可能是至关重要的。

您可以像这样解决性能问题:

db.collection.aggregate([
    {
        $facet: {
            one: [
                {
                    $match: {
                        fieldA: { $ne: 0 },
                    },
                },
                {
                    $lookup: { from: 'collectionA', localField: 'fieldA', foreignField: 'fieldA', as: 'agg' },
                },
                {
                    $match: {
                        'agg.0': { $exists: true },
                    },
                },
            ],
            two: [
                {
                    $match: {
                        fieldA: { $eq: 0 },
                    },
                },
                {
                    $lookup: { from: 'collectionA', localField: 'fieldB', foreignField: 'fieldB', as: 'agg' },
                },
                {
                    $match: {
                        'agg.0': { $exists: true },
                    },
                },
            ],
        },
    },
    {
        $addFieldS: {
            combined: {
                $concatArrays: [
                    '$one',
                    '$two',
                ],
            },
        },
    },
    {
        $unwind: '$combined',
    },
    {
        $replaceRoot: {
            newRoot: "$combined"
        },
    },
]);

虽然这里有一些开销,但它仍然比非索引查找更快。