使用某些过滤器MongoDB检索n个随机文档

时间:2019-01-15 15:16:16

标签: javascript node.js mongodb mongoose

我需要根据给定的限制从随机文档的集合中检索。 如果提供了一些过滤器,则应添加它们以过滤响应结果。我可以根据提供的字段来构建匹配项和大小,但是即使在我打电话时,我也有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
      });
    });

1 个答案:

答案 0 :(得分:1)

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

因此,最后您需要在$match阶段之后推动$sample阶段。订单应该是

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)