首页 > 解决方案 > 如何在 MongoDB 中的 $lookup 文档上编写 $match

问题描述

我有两个如下所示的 MongoDB 集合:

Products      Specials
----------    ----------
_id           _id
name          product_id
country       zip
price         percent_discount
              out_of_stock

我也在使用 GraphQL,所以我编写了一个聚合管道,以这种结构返回数据:

specials {
  _id
  product {
    _id
    name
    country
    price
  }
  zip
  percent_discount
  out_of_stock
}

我写的这个聚合管道效果很好,看起来像这样:

let response = await Specials.aggregate([
    {
        $lookup: {
            from: 'products',
            localField: 'product_id',
            foreignField: '_id',
            as: 'product'
        }
    },
    {
        $unwind: '$product'
    },
    {
        $match: {
            zip: zip
        }
    }
])

return response;

现在我正在尝试在其中添加一个过滤器。过滤器应与产品集合中的名称或国家/地区匹配,最好使用正则表达式。所以我试着写这样的东西,但是当应该只有 2-3 个时它会产生超过 8000 个结果:

let response = await Specials.aggregate([
    {
        $match: { zip: zip }
    },
    {
        $lookup: {
            from: "products",
            let: { product_id: "$product_id" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                {
                                    _id: "$$product_id"
                                },
                                {
                                    $or: [
                                        {
                                            name: filter
                                        },
                                        {
                                            country: filter
                                        }
                                    ]
                                }
                            ]
                        }
                    }
                }
            ],
            as: "product"
        }
    },
    {
        $unwind: "$product"
    }
])

标签: mongodbaggregation-framework

解决方案


如果您使用的是 Mongo 4.2+ 版,则可以使用$regexMatch

let response = await Specials.aggregate([
    {
        $lookup: {
            from: "products",
            let: { product_id: "$product_id" },
            pipeline: [
                {
                    $match: {
                       $expr: {
                            $and: [
                                {
                                    $eq: ["$$product_id", "$_id"]
                                },
                                {
                                    $or: [
                                        {
                                            $regexMatch: { input: "$name", regex: filterRegex }
                                        },
                                        {
                                            $regexMatch: { input: "$country", regex: filterRegex }
                                        }
                                    ]
                                }
                            ]
                        }
                    }
                }
            ],
            as: "product"
        }
    },
    {
        $unwind: "$product"
    },
    {
        $match: {
            $and: [
                {
                    zip: zip
                }
            ]
        }
    }
])

return response;

推荐阅读