我try 使用aggregate$lookup将PostgreSQL查询(来自Vercel的nextjs仪表板教程)转换为MongoDB查询. 我知道如何聚合多个集合并为一个参数进行筛选.以及如何用$or运算符查询一个集合的多个参数.

我遇到的问题是,查询使用多个搜索参数搜索多个集合.我想不出一种方法来将其合并到一个聚合管道中.

我搜索了现有的问题,但只找到一个问题,上面说这是不可能的. 所以我的问题是,这是可能的吗?如果可能,如何实现?

这就是SQL的样子:

SELECT
  invoices.customer_id,
  invoices.amount,
  invoices.status,
  customers.name
FROM invoices
JOIN customers ON invoices.customer_id = customers.id
WHERE
  customers.id ILIKE ${`%${query}%`} OR
  customers.name ILIKE ${`%${query}%`} OR
  invoices.amount::text ILIKE ${`%${query}%`} OR
  invoices.status ILIKE ${`%${query}%`}
ORDER BY invoices.amount DESC

以下是这些Collection 品的外观:

db={
  "invoices": [
    {
      "customer_id": "10",
      "amount": 15795,
      "status": "pending"
    },
    {
      "customer_id": "20",
      "amount": 20348,
      "status": "paid"
    }
  ],
  "customers": [
    {
      "id": "10",
      "name": "Delba de Oliveira"
    },
    {
      "id": "20",
      "name": "Lee Robinson"
    }
  ]
}

推荐答案

你的invoices.amountNumber,所以你不能对数据类型为Number的字段执行正则表达式.在PostgreSQL中,你可以使用invoices.amount::text,而在MongoDB中,有$toString操作符.

在这个使用aggregate的示例中,您需要使用$lookup连接两个集合,使用invoice.customer_id作为localField,以匹配cusotmers.id作为foreignField.

我假设您希望将invoices.amount保留为Number数据类型,这样您就可以使用$addFields添加一个临时字段,该字段将保存invoices.amount的字符串版本.这样,正则表达式就可以使用它来执行查询.

此后,您可以使用$project Select 要在输出中显示的字段:

db.invoices.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customer_id",
      foreignField: "id",
      as: "customer"
    }
  },
  {
    $addFields: {
      amountAsString: {
        $toString: "$amount"
      }
    }
  },
  {
    $match: {
      $or: [
        {
          "customer.id": {
            $regex: query,
            $options: "i"
          }
        },
        {
          "customer.name": {
            $regex: query,
            $options: "i"
          }
        },
        {
          amountAsString: {
            $regex: query,
            $options: "i"
          }
        },
        {
          status: {
            $regex: query,
            $options: "i"
          }
        }
      ]
    }
  },
  {
    $unwind: "$customer"
  },
  {
    $project: {
      customer_id: 1,
      amount: 1,
      status: 1,
      name: "$customer.name"
    }
  },
  {
    $sort: { amount: -1 }
  }
])

有关工作示例,请参见HERE.

Note:根据我的经验,在执行查询之前,最好知道你想在哪个集合上执行regex查询.这种包罗万象的方法效率很低,因为您需要连接两个集合,然后执行$match阶段.如果你可以通过编程方式预先知道你想要查询[idname]或[amountstatus],那么你可以显著提高查询性能.

Node.js相关问答推荐

Node.js promise 循环中的所有多个API调用

为高流量网站优化Node.js实时通知服务

赫斯基添加命令已弃用?

如何在RavenDB中执行JS索引?

NPM:一般的npm二进制依赖可以静态构建吗?

我的Node.js应用程序没有将Mongoose方法findByIdAndDelete作为函数进行检测

通过PutObjectCommand上传AWS S3 PDF文件,结果为空PDF

Axios TypeError:将循环 struct 转换为 JSON

在mongoose虚拟属性中处理异步操作

将文件传递到 AWS lambdas(nodejs) + API 网关后重新上传文件

TypeError:在使用 Jest、Supertest、Express、Typescript 进行测试时无法读取未定义的属性(读取listen)

错误:找不到模块'C:\Users\nguye\AppData\Local\nodejs\node_modules\npm\bin\npm-cli.js'

NodeJS 后端发布请求将数据作为NULL值发布到 SQL Server 表

类 WebSwapCGLLayer 在 Mac OS X /System 和 node_modules 中都实现了

使用 $in 查询时,如何获取 mongoDB 中每个唯一 ID 的 n 个文档?

带有加密的nodejs中的SALT和HASH密码

在单独的模块中定义 Mongoose 模型

Mongoose - 保存字符串数组

fs.createWriteStream 不会立即创建文件?

如何使用 cookie 创建 HTTP 客户端请求?