首页 > 解决方案 > Mongodb聚合查询$skip $limit问题

问题描述

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

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']
      }
    }

标签: node.jsmongodbmongoose

解决方案


好吧,在挖掘和挖掘之后,我发现了一个解决了我的问题的github 问题,希望这将在未来对其他人有所帮助。使用时Model.aggregate,Mongoose 不会强制转换它的参数。

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

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

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


推荐阅读