日期数组的MongoDB过滤查询返回空数组

时间:2020-03-04 03:19:39

标签: mongodb mongodb-query aggregation-framework

我有一个MongoDB文档,其中包含有关产品及其变体的信息,结构示例如下。

{
    "site_id": 3,
    "status": 2,
    "tags": [],
    "title": "WORTHBUY Bento Lunch Box for Kids, 2 Compartments Stainless Steel Square Lunch Box with Portable Cutlery, Portion Control Food Storage Container Leakproof, BPA Free(Pink)",
    "total_sold_count": 3,
    "amount_of_variations": 3,
    "variations": [{
            "price": 9.66,
            "shipping_price": 0,
            "quantity": 0,
            "sold_count": 1,
            "sold_dates": [
                ISODate("2020-03-03T17:00:00.000-07:00")
            ]
        },
        {
            "price": 18.42,
            "shipping_price": 0,
            "quantity": 0,
            "sold_count": 1,
            "sold_dates": [
                ISODate("2020-03-03T17:00:00.000-07:00")
            ]
        },
        {
            "price": 18.42,
            "shipping_price": 0,
            "quantity": 0,
            "sold_count": 1,
            "sold_dates": [
                ISODate("2020-03-03T17:00:00.000-07:00"),
                ISODate("2020-03-09T20:30:56.000-06:00")
            ]
        }
    ]
}

我正在尝试获取在特定日期之后售出的所有变体。为此,我使用了以下mongo聚合查询,但是在结果中,我得到了一个空的变体列表。

db.products.aggregate([{
    $match: {
        "variations.sold_dates": {
            $gt: ISODate("2020-03-05 00:00:00")
        }
    }
}, {
    $addFields: {
        "variations": {
            $filter: {
                input: "$variations",
                as: "variations",
                cond: {
                    $and: [{
                        $gt: ["$$variations.sold_dates", ISODate("2020-03-05 00:00:00")]
                    }]
                }
            }
        }
    }
}])

此查询对我尝试过的除此日期列表以外的所有其他字段起作用。知道我在做什么错吗?

2 个答案:

答案 0 :(得分:2)

由于 variations.sold_dates 是日期数组,因此您不能比较给定的日期大于 sold_dates 的日期。因此,您需要迭代 variations.sold_dates 数组的每个元素,并检查大于迭代的次数,因为$filter返回一个过滤器元素数组,然后您可以检查该数组的大小> 0将变体对象添加到$addFields中的变体数组中。试试这个查询:

db.collection.aggregate([
  {
    $match: {
      "variations.sold_dates": {
        $gt: ISODate("2020-03-05T00:00:00Z")
      }
    }
  },
  {
    $addFields: {
      "variations": {
        $filter: {
          input: "$variations",
          as: "variation",
          cond: {
            $gt: [
              {
                $size: {
                  $filter: {
                    input: "$$variation.sold_dates",
                    cond: {
                      $gt: [
                        "$$this",
                        ISODate("2020-03-05T00:00:00.000Z")
                      ]
                    }
                  }
                }
              },
              0
            ]
          }
        }
      }
    }
  }
])

测试: MongoDB-Playground

答案 1 :(得分:0)

这是另一个解决方案:

db.collection.aggregate([
   {
      $set: {
         "variations": {
            $filter: {
               input: "$variations",
               as: "variation",
               cond: {
                  $anyElementTrue: {
                     $map: {
                        input: "$$variation.sold_dates",
                        in: { $gt: ["$$this", ISODate("2020-03-05T00:00:00.000Z")] }
                     }
                  }
               }
            }
         }
      }
   }
])

根据您的要求,您可以将$anyElementTrue替换为$allElementsTrue