【问题标题】:How can i do Mongodb aggrigate filter for multiple collection?我怎样才能为多个集合做 Mongodb 聚合过滤器?
【发布时间】:2021-05-20 10:36:14
【问题描述】:

我有两个托收预订和发票,我已经准备好汇总和查找以下条件的查询

取票条件

条件 1:状态不等于已交付

条件 2:产品不应为 null 或为空

条件 3:productID 应存在于 products 数组中且不应为空

条件 4:IsDeliveryFailed 不应为“是”

预订收集数据

{
    "_id" : ObjectId("609a382b589346973c84c6fe"),
    "Name" : "abc",
    "UserId":1
    "Status" : "Pending", 
    "Invoices" : [ 
        ObjectId("709a382b5c6fe89346973c84")
    ],  
    "BookingData" : {
        "Date" : ISODate("2021-04-30T04:00:00.000Z"),
        "info" : [],
        "BookingDataMethod" : "avf",
        "Message" : null,
        "products" : [ 
            {
                "_id" : ObjectId("60a4e92775e5de3570578820"),
                "ProductName" : "Test1",
                "ProductID" : ObjectId("60a4e92475e5de357057880a"),
                "IsDeliveryFailed" : "Yes"
            }, 
            {
                "_id" : ObjectId("60a4e92775e5de357057881f"),
                "ProductName" : "Test2",
                "ProductID" : ObjectId("60a4e92475e5de357057880d")
            }
        ],
        
    }
    
}

发票收取条件

条件 1:InvoiceData 不应为 null 或为空

条件 2:InvoiceID 应存在于 InvoiceData 数组中且不应为空

条件 3:IsPaymentFailed 不应为“是”

发票收集数据

{
    "_id" : ObjectId("709a382b5c6fe89346973c84"),    
    "invoiceNumber":1
    "InvoiceData" :[
            {
                "_id" : ObjectId("60a4e92775e5de3570578820"),
                "ProductName" : "Test1",
                "InvoiceID":1,
                "IsPaymentFailed" : "Yes"
            }, 
            {
                "_id" : ObjectId("60a4e92775e5de357057881f"),
                "InvoiceID":2,
                "ProductName" : "Test2",
                
            }
    
    ]
    
}

查询

db.bookings.aggregate([
  {
    "$match": {
      "Status": {
        $ne: "Delivered"
      }
    }
  },
  {
    "$lookup": {
      "from": "invoices",
      "localField": "Invoices",
      "foreignField": "_id",
      "as": "invoiceInfo"
    }
  },
  {
    "$match": {
      "$or": [
        {
          "BookingData.products": {
            "$exists": true
          }
        },
        {
          "invoiceInfo.InvoiceData": {
            "$exists": true
          }
        }
      ]
    }
  },
 {
    $set: {
      "BookingData.products": {
        "$filter": {
          "input": "$BookingData.products",
          "cond": {
            $and: [
              { $ne: [ "$$this.ProductID", undefined ] },
              { $ne: [ "$$this._id", null ] },
              { $ne: [ "$$this.IsDeliveryFailed", "Yes" ] }
            ]
          }
        }
      }
    }
  },
 {
    $set: {
      "invoiceInfo.InvoiceData": {
        "$filter": {
          "input": "$invoiceInfo.InvoiceData",
          "cond": {
            $and: [
              { $ne: [ "$$this.InvoiceID", undefined ] },
              { $ne: [ "$$this._id", null ] },
              { $ne: [ "$$this.IsPaymentFailed", "Yes" ] }
            ]
          }
        }
      }
    }
  },
  {
    $match: {
      $expr: {
        $or: [
          {
            $ne: [
              "$BookingData.products",
              [],
              
            ]
          },
          {
            $ne: [
              "$invoiceInfo.InvoiceData",
              [],
              
            ]
          }
        ]
      }
    }
  }
  
])

这不按预期工作,例如,如果

查询应该返回上述文档

如果 ProductID 存在且产品存在且所有产品都没有 IsDeliveryFailed:“是”

如果 ProductID 存在且产品存在并且任何产品都没有 IsDeliveryFailed:“是”

如果 InvoiceID 存在且 InvoiceData 存在且所有 InvoiceData 都没有 IsPaymentFailed:“是”

如果 InvoiceID 存在且 InvoiceData 存在并且任何 InvoiceData 不存在 IsPaymentFailed:“是”

另一组

如果 ProductID 存在且产品存在且所有产品均为 IsDeliveryFailed:“是”标志。但我们必须检查发票收集 如果 InvoiceID 存在且 InvoiceData 存在并且任何 InvoiceData 都没有 IsPaymentFailed: "Yes" 那么我们必须返回此文档

如果 InvoiceID 存在并且 InvoiceData 存在并且所有 InvoiceData 都是 IsPaymentFailed:“是”。但是我们必须检查预订集合 如果 ProductID 存在并且产品存在并且任何产品都没有 IsDeliveryFailed:"Yes" 那么我们必须返回文档

Mongo playground

【问题讨论】:

  • 你的invoiceInfo 是一个数组吗?还是总是只有一个元素?
  • invoiceInfo 将是一个数组

标签: node.js mongodb mongodb-query aggregation-framework


【解决方案1】:

我已经在Question 中解释了您之前的问题。由于 invoiceInfo 是一个数组,invoiceData 也是 invoiceInfo 内部的一个数组,我们使用 map 和 filter。然后我们需要排除invoiceData的空数组。 (这可以在前面的步骤中完成,也可以像 filter-map->filter 一样,但它可能很长,这就是我在下一阶段使用它的原因)

这里是代码

db.bookings.aggregate([
  {
    "$match": {
      "PaymentStatus": { $ne: "Delivered" }
    }
  },
  {
    $set: {
      "BookingData.products": {
        "$filter": {
          "input": "$BookingData.products",
          "cond": {
            $and: [
              { $ne: [ "$$this.ProductID", undefined ] },
              { $ne: [ "$$this._id", null ] },
              { $ne: [ "$$this.IsDeliveryFailed", "Yes" ] }
            ]
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "invoices",
      "localField": "Invoices",
      "foreignField": "_id",
      "as": "invoiceInfo"
    }
  },
  {
    $set: {
      invoiceInfo: {
        $map: {
          input: "$invoiceInfo",
          as: "info",
          in: {
            InvoiceData: {
              $filter: {
                input: "$$info.InvoiceData",
                as: "data",
                "cond": {
                  $and: [
                    { $ne: [ "$$data.InvoiceID", undefined ] },
                    { $ne: [ "$$data.InvoiceID", null ] },
                    { $ne: [ "$$data.IsPaymentFailed", "Yes" ] }
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $set: {
      invoiceInfo: {
        $filter: {
          input: "$invoiceInfo",
          cond: { $ne: [ "$$this.InvoiceData", [] ] }
        }
      }
    }
  },
  {
    $match: {
      $expr: {
        $or: [
          { $ne: [ "$BookingData.products", [] ] },
          { $ne: [ "$invoiceInfo", [] ] }
        ]
      }
    }
  }
])

工作Mongo playground

希望这会对您有所帮助。这是您需要根据您的要求进行游戏/解决方法的时间。有时您需要在演示中的当前位置之前或之后进行查找

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多