首页 > 解决方案 > 使用某些过滤器检索 n 个随机文档 MongoDB

问题描述

我需要根据给定的限制从一组随机文档中检索。如果提供了一些过滤器,则应添加它们以过滤响应的结果。我可以根据提供的字段来构建匹配和大小,但即使我有 20 个符合过滤器的文档,当我拨打电话时,我也只收到 2 或 3 个文档,我似乎无法弄清楚。如果我只设置限制,它确实会根据限制返回 N 个随机文档,但如果我添加一个过滤器,它不会给我想要的结果。

这就是我现在所做的

const limit = Number(req.query.limit || 1);

  const difficulty = req.query.difficulty;
  const category = req.query.category;
  const settings = [
    {
      $sample: {
        size: limit
      }
    }
  ];

  if (difficulty && category) {
    settings.push({
      $match: {
        difficulty: difficulty,
        category: category
      }
    });
  } else if (difficulty && category == null) {
    settings.push({
      $match: {
        difficulty
      }
    });
  }

  if (difficulty == null && category) {
    settings.push({
      $match: {
        category
      }
    });
  }
  console.log(settings);

  Question.aggregate(settings)
    .then(docs => {
      const response = {
        count: docs.length,
        difficulty: difficulty ? difficulty : "random",
        questions:
          docs.length > 0
            ? docs.map(question => {
                return {
                  _id: question._id,
                  question: question.question,
                  answers: question.answers,
                  difficulty: question.difficulty,
                  category: question.category,
                  request: {
                    type: "GET",
                    url:
                      req.protocol +
                      "://" +
                      req.get("host") +
                      "/questions/" +
                      question._id
                  }
                };
              })
            : {
                message: "No results found"
              }
      };

      res.status(200).json(response);
    })
    .catch(err => {
      res.status(500).json({
        error: err
      });
    });

标签: javascriptnode.jsmongodbmongoose

解决方案


阶段的顺序在这里很重要。您正在推动$match阶段之后的$sample阶段,首先将整个文件放入$size整个文件,然后将$match阶段应用于文件文件。$sampled

所以最后你需要在$sample舞台之后推动$match舞台。顺序应该是

const limit = Number(req.query.limit || 1);

  const difficulty = req.query.difficulty;
  const category = req.query.category;
  const settings = []

  if (difficulty && category) {
    settings.push({
      $match: {
        difficulty: difficulty,
        category: category
      }
    })
  } else if (difficulty && category == null) {
    settings.push({
      $match: {
        difficulty
      }
    })
  }

  if (difficulty == null && category) {
    settings.push({
      $match: {
        category
      }
    })
  }

  setting.push({
    $sample: {
      size: limit
    }
  })
  console.log(settings);

  Question.aggregate(settings)

推荐阅读