【问题标题】:Query a subdocument and select filtered data from it Mongoose查询子文档并从中选择过滤后的数据 Mongoose
【发布时间】:2021-10-23 06:07:33
【问题描述】:

我想查询位于父文档中的子文档,并且只选择(在快速响应中返回)具有自己数据的特定子文档,但我这样做的方式是选择/返回所有子文档,没有过滤我需要的,我试图通过字段candidateId进行过滤

这是我的查询:

interviewRouter.get(
  "/:idCandidato&:userEmail",
  async (req: Request, res: Response) => {
    const { idCandidato, userEmail } = req.params;

    parseInt(idCandidato);

    const infoCandidato = await User.find({
      email: userEmail,
      "candidates.candidateId": idCandidato,
    }).select({"_id": 0, "candidates": 1});

    infoCandidato
      ? res.status(200).json({ Candidato: infoCandidato })
      : res.status(404).json({ Candidato: "Candidato no encontrado" });
  }
);

这是我的文档和子文档结构:

{
    "_id" : ObjectId("61223b3c88e21fe0ee69d689"),
    "username" : "randomUserName",
    "email" : "random@email.com",
    "pictureUrl" : "some/url/to/the/user/picture/username",
    "role" : "admin",
    "candidates" : [
        {
            "_id" : ObjectId("612242cd11a7f1ebc6a18661"),
            "candidateName" : "some candidates name",
            "candidateId" : 123,
            "candidateInfo" : [
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a18662"),
                    "currentSituation" : "3",
                    "motivationToChange" : "3",
                    "postSavingDate" : ISODate("2021-08-22T12:27:57.490Z")
                },
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a04854"),
                    "currentSituation" : "6",
                    "motivationToChange" : "7",
                    "postSavingDate" : ISODate("2021-08-22T13:56:57.490Z")
                }
            ],
            "availableNow" : false,
            "mainSkills" : "MM"
        },
        {
            "_id" : ObjectId("612261abf7b68bfaf56345df"),
            "candidateName" : "some other guy",
            "candidateId" : 1234,
            "candidateInfo" : [
                {
                    "_id" : ObjectId("612261abf7b68bfaf56345e0"),
                    "currentSituation" : "dunno",
                    "motivationToChange" : "no idea",
                    "postSavingDate" : ISODate("2021-08-22T14:39:39.161Z")
                }
            ],
            "availableNow" : false,
            "mainSkills" : "JavaScript"
        }
    ],
    "__v" : 0
}

在下面,您可以看到我的查询返回的内容,基本上是整个 candidates 集合,而不是我需要的过滤后的子文档

{
    "Candidato": [
        {
            "candidates": [
        {
            "_id" : ObjectId("612242cd11a7f1ebc6a18661"),
            "candidateName" : "some candidates name",
            "candidateId" : 123,
            "candidateInfo" : [
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a18662"),
                    "currentSituation" : "3",
                    "motivationToChange" : "3",
                    "postSavingDate" : ISODate("2021-08-22T12:27:57.490Z")
                },
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a04854"),
                    "currentSituation" : "6",
                    "motivationToChange" : "7",
                    "postSavingDate" : ISODate("2021-08-22T13:56:57.490Z")
                }
            ],
            "availableNow" : false,
            "mainSkills" : "MM"
        },
        {
            "_id" : ObjectId("612261abf7b68bfaf56345df"),
            "candidateName" : "some other guy",
            "candidateId" : 1234,
            "candidateInfo" : [
                {
                    "_id" : ObjectId("612261abf7b68bfaf56345e0"),
                    "currentSituation" : "dunno",
                    "motivationToChange" : "no idea",
                    "postSavingDate" : ISODate("2021-08-22T14:39:39.161Z")
                }
            ],
            "availableNow" : false,
            "mainSkills" : "JavaScript"
        }
            ]
        }
    ]
}

重要提示:请记住,我只希望它返回1231234 子文档,具体取决于我传递给查询的candidateId

这是我找到的解决方法,但我认为有点脏,希望有另一种选择:


interviewRouter.get(
  "/:idCandidato&:userEmail",
  async (req: Request, res: Response) => {
    const { idCandidato, userEmail } = req.params;

    const infoCandidato = await User.findOne(
      {
        email: userEmail,
        "candidates.candidateId": idCandidato,
      },
      function (err: any, response: any) {
        if (err) {
          res.status(400).send(err);
        } else {
          let newResponse = response["candidates"].filter((element: any) => {
            return element.candidateId === parseInt(idCandidato);
          });
          res.status(200).json({ Candidato: newResponse });
        }
      }
    );

通过这种解决方法,我得到了我需要的东西,但它看起来有点乱,我觉得可能还有其他更清洁的解决方案。这是我得到的回报:

{
    "Candidato": [
        {
            "_id" : ObjectId("612242cd11a7f1ebc6a18661"),
            "candidateName" : "some candidates name",
            "candidateId" : 123,
            "candidateInfo" : [
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a18662"),
                    "currentSituation" : "3",
                    "motivationToChange" : "3",
                    "postSavingDate" : ISODate("2021-08-22T12:27:57.490Z")
                },
                {
                    "_id" : ObjectId("612242cd11a7f1ebc6a04854"),
                    "currentSituation" : "6",
                    "motivationToChange" : "7",
                    "postSavingDate" : ISODate("2021-08-22T13:56:57.490Z")
                }
            ],
            "availableNow" : false,
            "mainSkills" : "MM"
        },
    ]
}

有什么想法吗?谢谢!

@eol 解决的问题 - 简单说明

如前所述,@eol 解决了问题并分享了解决方案。我接受了他的回答并将其翻译成 JavaScript/Mongoose sintaxis,就这样:

interviewRouter.get(
  "/:idCandidato&:userEmail",
  async (req: Request, res: Response) => {
    const { idCandidato, userEmail } = req.params;
    const infoCandidato = await User.aggregate([
      {
        "$match": {
          email: userEmail
        }
      },
      {
        "$unwind": "$candidates"
      },
      {
        "$match": {
          "candidates.candidateId": parseInt(idCandidato)
        }
      }]);
      infoCandidato.length !== 0
      infoCandidato
      ? res.status(200).json({ Candidato: infoCandidato })
      : res.status(404).json({ Candidato: "Candidato no encontrado" });
  }
);

【问题讨论】:

    标签: node.js express mongoose mongodb-query


    【解决方案1】:

    您可以进行简单的聚合,首先$match 具有给定email 的文档,然后$unwind 候选元素和过滤器$match 给定id 的那些:

    db.collection.aggregate([
      {
        "$match": {
          email: "random@email.com"
        }
      },
      {
        "$unwind": "$candidates"
      },
      {
        "$match": {
          "candidates.candidateId": 1234
        }
      }
    ])
    

    这是 mongoplayground 上的一个示例:https://mongoplayground.net/p/GPB3oYqe5em

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-18
      • 2021-03-23
      • 2019-07-13
      • 2020-07-16
      • 1970-01-01
      • 2023-03-20
      • 2015-04-27
      • 1970-01-01
      相关资源
      最近更新 更多