mongodb sort 命令在多个条件下对数据库进行排序

mongodb sort command to sort database on multiple conditions

所以在我为 mongodb 设置的查询中,我试图找到与特定关键字或类别匹配的所有产品,这有效,但不一定有效,因为我想对这些产品进行排序最高价,但前提是我有这些产品的库存。

我当前的实现如下所示:

const getProducts = asyncHandler(async (req, res) => {
  try {
    const pageSize = 10;
    const page = Number(req.query.pageNumber) || 1;
    const keyword = req.query.keyword
      ? {
          name: {
            $regex: req.query.keyword,
            $options: "i",
          },
        }
      : {};
    const category = req.query.category
      ? { category: { $regex: req.query.category, $options: "i" } }
      : {};
    const count = await Product.countDocuments({ ...keyword, ...category });
    const products = await Product.find({ ...keyword, ...category })
      .limit(pageSize)
      .skip(pageSize * (page - 1))
      .sort({ countInStock: -1, createdAt: -1 })
      .populate("categories.category", "id cat_name slug");

    res.json({
      products,
      page,
      pages: Math.ceil(count / pageSize),
      prevPage: page - 1,
      nextPage: page + 1,
    });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: `Server Error: ${error.message}` });
  }
});

在我的 .sort 命令中发生的事情是它首先对库存中最高数量的商品的查询进行排序,而不考虑它们的价格,然后在它们的创建日期对其余产品进行排序,这不是我想要的逻辑,但它是我目前正在使用的逻辑。我看过一些使用 aggregate 命令对数据库进行排序的 SO 文章,但我不确定如何在我当前的设置中使用它。因为,聚合不只是 return 匹配条件吗?如果匹配条件是一个 {} 对象,它仍然会以与 find() 命令相同的方式运行吗?

---更新--- 我已经开始着手实施聚合命令而不是 find() 命令,但是,它的...工作完全一样,与 find?

相同
const products = await Product.aggregate([
      {
        $match: {
          $expr: { keyword, category },
        },
      },
      {
        $sort: {
          countInStock: -1,
          price: -1,
        },
      },
    ])
      .limit(pageSize)
      .skip(page)
      .populate("categories.category", "id cat_name slug");

它仍然没有在两种情况下排序,它按 countInStock 然后 price 对项目进行排序,但不是同时进行。我想要价格最高的商品,我先有货,然后才是最...我可能想多了。

它们都包含在排序中,但结果集是根据库存单位数量排序,然后是价格排序。这可能会让人觉得价格在排序过程中被忽略了。

通常的解决方法是使用 $project 或 $addFields 步骤添加辅助字段。在这种情况下,根据库存状态添加 01 字段是有意义的。

await Product
  .aggregate([{
    $match: {
      $expr: {
        keyword,
        category
      },
    },
  }, {
    $addFields: {
      isInStock: { // Helper field. This is 1 if there are items in stock.
        $cond: {
          if: "$countInStock",
          then: 1,
          else: 0
        }
      }
    }
  }, {
    $sort: {
      isInStock: -1,
      price: -1,
    },
  }, {
    $skip: page
  }, {
    $limit: pageSize
  }])
  .populate("categories.category", "id cat_name slug");

注意模型种群可以使用聚合步骤来写$lookup,让代码更简洁