首页 > 解决方案 > 在 Mongo 中填充后如何查询包含相同用户名的所有文档

问题描述

我正在尝试获取与具有相同值的用户名字段匹配的所有文档。

前任。如果用户名是 Mabel,则返回填充后用户名与名称 Mabel 匹配的每个文档

项目模型:

{
    "_id": "5e641a033ecd5c172827eba6",
    "title": "My Post",
    "description": "First post",
    "userId": "5e431ba109c629018d664d89",
    "createdAt": "2020-03-07T22:02:43.758Z",
    "__v": 0
}

填充后:(用户模型填充在项目模型中)

{
    "_id": "5e641a033ecd5c172827eba6",
    "title": "My Post",
    "description": "First post",
    "userId": {
        "role": "user",
        "_id": "5e431ba109c629018d664d89",
        "username": "Mabel",
        "createdAt": "2020-02-11T21:24:49.932Z"
    },
    "createdAt": "2020-03-07T22:02:43.758Z",
    "__v": 0
}

我尝试了什么:

const projects = await Projects.find().populate({
    path: "userId",
    match: { username: { $in: username } }
  });

但最终会从所有其他用户名中获取所有文档。

我需要的?

现在,Mabel 创建了三个项目。这三个项目属于同一个 userId.username。如何从该用户名查询所有这些文档?

标签: mongodbmongooseaggregation-framework

解决方案


我猜你是想用他/她的项目来吸引用户。

您可以使用聚合框架轻松完成此操作。

我们首先将用户与用户名匹配,然后使用$lookup聚合来获取他/她的项目。

const Users = require("../models/user");   //CHANGE this path according to your user model 
const Projects = require("../models/project");  //CHANGE this path according to your project model 

router.get("/users", async (req, res) => {
  let username = "Mabel";
  const result = await Users.aggregate([
    {
      $match: {
        username: username
      }
    },
    {
      $lookup: {
        from: "projects",  //MUST be the physical name of the collection
        localField: "_id",
        foreignField: "userId",
        as: "projects"
      }
    }
  ]);

  res.send(result);
});

操场

样本文件:

db={
  "users": [
    {
      "_id": "5e6a293637a3d101b488278d",
      "username": "Mabel",
      "role": "user",
      "__v": 0
    },
    {
      "_id": "5e6a294537a3d101b488278e",
      "username": "Tom",
      "role": "user",
      "__v": 0
    },
    {
      "_id": "5e6a294f37a3d101b488278f",
      "username": "Bob",
      "role": "user",
      "__v": 0
    }
  ],
  "projects": [
    {
      "_id": "5e6a298537a3d101b4882790",
      "title": "My Post",
      "description": "First post",
      "userId": "5e6a293637a3d101b488278d",
      "__v": 0
    },
    {
      "_id": "5e6a29a237a3d101b4882791",
      "title": "My Post 2",
      "description": "Second post",
      "userId": "5e6a293637a3d101b488278d",
      "__v": 0
    },
    {
      "_id": "5e6a29bd37a3d101b4882792",
      "title": "Tom post",
      "description": "Tom post description",
      "userId": "5e6a294537a3d101b488278e",
      "__v": 0
    },
    {
      "_id": "5e6a2a0837a3d101b4882793",
      "title": "Bob post",
      "description": "Bob post description",
      "userId": "5e6a294f37a3d101b488278f",
      "__v": 0
    }
  ]
}

输出:

[
  {
    "__v": 0,
    "_id": "5e6a293637a3d101b488278d",
    "projects": [
      {
        "__v": 0,
        "_id": "5e6a298537a3d101b4882790",
        "description": "First post",
        "title": "My Post",
        "userId": "5e6a293637a3d101b488278d"
      },
      {
        "__v": 0,
        "_id": "5e6a29a237a3d101b4882791",
        "description": "Second post",
        "title": "My Post 2",
        "userId": "5e6a293637a3d101b488278d"
      }
    ],
    "role": "user",
    "username": "Mabel"
  }
]

第二种选择

如果要使用填充而不是聚合,则需要设置虚拟填充。因为我们在用户内部没有项目引用。

因此,要设置虚拟填充,我们在用户模式中进行以下更改:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const UserSchema = new Schema(
  {
    username: String,
    role: String
  },
  {
    toJSON: { virtuals: true } //don't forget this option
  }
);

UserSchema.virtual("projects", {
  ref: "Project", // Project here must match mongoose.model("Project", ProjectSchema);
  foreignField: "userId",
  localField: "_id"
});

module.exports = mongoose.model("User", UserSchema);

现在我们可以像这样获取用户和他/她的项目:

router.get("/users", async (req, res) => {
  let username = "Mabel"; 

  const result = await Users.find({ username }).populate("projects");

  res.send(result);
});

推荐阅读