【问题标题】:MongoDB Aggregate - How to implement match and lookup如何在聚合 mongoDB 中实现匹配和查找?
【发布时间】:2022-02-12 20:33:49
【问题描述】:

我需要从两个集合(费用、帐户)中获取数据。数据必须介于给定日期范围和金额范围之间。
日期、金额、货币、类型费用集合和accountId中以 _id 身份在 account 集合中。 我尝试了以下查询,但没有返回任何内容

const response = await Expense.aggregate( [
            { $match: { 
                $and: [
                    {
                        currency: "1",
                        expenseType: "1"
                    },
                    {
                        date: {
                            $gte: new Date(date.value.from) , $lte: new Date(date.value.to) 
                        },
                        amount: {
                            $gt: parseFloat(amount.value.from) , $lt: parseFloat(amount.value.to)
                        }
                    }
                ],
                
            } },
            {
                $lookup:
                  {
                    from: "accounts",
                    localField: "accountId",
                    foreignField: "_id",
                    as: "account"
                  }
             }
         ] )

这是费用收集的架构

费用收款单

收款凭证

【问题讨论】:

  • 您好,您能提供这两个集合的样本数据吗?同时,Expense 文档中是否存在type 字段?正如我所见,您的费用架构中不存在该字段。谢谢。
  • 嘿,我已经更新了这个问题。正如您所问的,类型字段是费用类型。对于迟到的回复,我深表歉意。

标签: node.js database mongodb mongodb-query nosql


【解决方案1】:

从附加的 expense 文档中,amount 字段是 String 类型,但不是 Number 类型。

数据

amount: "20000"

架构

amount: {
  type: Number,
  required: true
}

您应该使用您的架构修改 MongoDB 中的 Expense 文档。


从您的聚合查询中,您需要将 amount 从字符串转换为十进制以进行比较。

解决方案 1:使用$expr

db.expense.aggregate([
  {
    $match: {
      $and: [
        {
          currency: "1",
          expenseType: "1"
        },
        {
          date: {
            $gte: new Date(date.value.from), 
            $lte: new Date(date.value.to) 
          },
          
        },
        {
          $expr: {
            $and: [
              {
                $gt: [
                  {
                    "$toDecimal": "$amount"
                  },
                  parseFloat(amount.value.from)
                ]
              },
              {
                $lt: [
                  {
                    "$toDecimal": "$amount"
                  },
                  parseFloat(amount.value.to)
                ]
              }
            ]
          }
        }
      ],
      
    }
  },
  {
    $lookup: {
      from: "accounts",
      localField: "accountId",
      foreignField: "_id",
      as: "account"
    }
  }
])

Solution 1 on Mongo Playground


解决方案 2:添加 $set 作为第一阶段

db.expense.aggregate([
  {
    $set: {
      amount: {
        "$toDecimal": "$amount"
      }
    }
  },
  {
    $match: {
      $and: [
        {
          currency: "1",
          expenseType: "1"
        },
        {
          date: {
            $gte: new Date(date.value.from),
            $lte: new Date(date.value.to)
          },
          amount: {
            $gt: parseFloat(amount.value.from),
            $lt: parseFloat(amount.value.to)
          }
        }
      ]
    }
  },
  {
    $lookup: {
      from: "accounts",
      localField: "accountId",
      foreignField: "_id",
      as: "account"
    }
  }
])

Solution 2 on Mongo Playground

【讨论】:

    猜你喜欢
    • 2020-06-29
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 2023-02-25
    • 2021-08-12
    • 2020-09-20
    • 1970-01-01
    • 2019-03-17
    相关资源
    最近更新 更多