MongoDB聚合查询$ skip $ limit问题

时间:2019-06-06 15:58:56

标签: node.js mongodb mongoose

我有一个从应用程序中调用的查询,以便为我提供数据库中的分页结果

const query = [
  {
    "$match" : {
      "$or" : [
        { "expires_at" : { "$gt" : moment().toISOString() }},
        { "expires_at" : null }
      ],
      "vendor_category" : {
        "$nin" : ignoredCategories
      }
    }
  },
  {
    "$lookup": {
      "from": models.retailers.collection.name,
      "localField": "retailer",
      "foreignField": "_id",
      "as": "retailer"
    }
  },
  {
    "$lookup": {
      "from": models.categories.collection.name,
      "localField": "category",
      "foreignField": "_id",
      "as": "category"
    }
  },
  {
    "$sort": {
      "category.popularity" : -1,
      ...sortBy
    }
  },
  { "$unwind": "$retailer" },
  { "$unwind": "$category" },
  { "$skip" : skip },
  { "$limit" : limit }
]

大多数情况下,我的两个$lookup$unwind对象将其他集合添加到结果中,而我的$sort对象则根据产品类别的受欢迎程度正确地对根查询进行了排序。

但是我的$match对象仅返回约18个结果(共72个结果)。很好,除了我运行const total = await models.products.countDocuments(query[0].$match)时,因此使用该匹配查询对文档进行计数,我得到72。所以两者之间不匹配。

那么其余的结果又如何了?我在此查询中做错了吗?这绝对是我编写的第一个汇总查询,因此也许我只是完全错过了一些东西。欢迎任何提示/问题/优化!如果您需要更多信息,请告诉我。

修改 这是展开的匹配查询的示例。当我为此使用Model.find时,它工作正常,但是由于我一直在隔离查询的各个部分,因此这似乎是罪魁祸首。目的是仅提取到期时间大于当前时间或字段为空的结果。数据来自刮板,有时我没有过期数据。我还排除了一类类别,这是为了防止显示通过刮板但无法在网站上显示的项目。

$match : {
       $or : [
         { expires_at : { $gt : moment().toISOString() }},
         { expires_at : null }
      ],
      vendor_category : {
        $nin : [ 'ID-6',   'ID-8', 'ID-283', 'ID-288', 'ID-354', 'ID-513', 'ID-654', 'ID-659', 'ID-33', 'ID-450', 'ID-497',  'ID-59', 'ID-404', 'ID-337']
      }
    }

1 个答案:

答案 0 :(得分:1)

在深入挖掘之后,我发现一个github issue解决了我的问题,希望这对以后的人们有所帮助。当使用Model.aggregate时,猫鼬不会转换其参数。

如果您希望使用Model.aggregate与日期匹配,则必须将日期包装在new Date()中。

最初,我这样做是行不通的:{ expires_at : { $gte : moment().toISOString() }}

并将其更改为此,它可以工作:{ expires_at : { $gte : new Date(moment().toISOString()) }}