【问题标题】:MongoDB Query that uses two collection使用两个集合的 MongoDB 查询
【发布时间】:2020-03-24 00:51:01
【问题描述】:

我是使用 MongoDB 的新手,我被困在编写查询的任务中。 我的问题陈述是我有两个集合

maening userId1=>follows userId2
+---------+---------+
| userId1 | userId2 |
+---------+---------+
| 1       | 2       |
+---------+---------+
| 1       | 3       |
+---------+---------+
| 1       | 4       |
+---------+---------+
| 2       | 3       |
+---------+---------+
| 3       | 1       |
+---------+---------+
second table is as follows
+---------+--------+----------------+
| tweetId | userId | tweetText      |
+---------+--------+----------------+
| ****    | 1      | Tweet By user1 |
+---------+--------+----------------+
| ****    | 2      | Tweet By user2 |
+---------+--------+----------------+
| ****    | 3      | Tweet By user3 |
+---------+--------+----------------+
| ****    | 4      | Tweet By user4 |
+---------+--------+----------------+

我希望我的结果包含 user1 关注的用户的所有推文...?????

【问题讨论】:

  • Nawaz 你能检查我的答案吗?如果是这样,请提供一些反馈,无论它是否适合您。
  • 是的!谢谢...我正在我的程序中实现这个...

标签: mongodb mongoose mongodb-atlas


【解决方案1】:

您需要像这样设计您的用户和推文模式:

用户:

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  username: String,
  follows: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "User"
    }
  ]
});

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

推文:

const mongoose = require("mongoose");

const tweetSchema = new mongoose.Schema({
  userId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User"
  },
  tweetText: String
});

module.exports = mongoose.model("Tweet", tweetSchema);

然后你可以使用下面的代码,插入用户、推文、获取用户及其关注者,以及用户关注者的推文:

索引.js

const express = require("express");
const app = express();
const mongoose = require("mongoose");
const url = "mongodb://localhost:27017/tweet"; //change url to your db
const User = require("./models/user");
const Tweet = require("./models/tweet");

const port = 3000;

app.use(express.json());

mongoose
  .connect(url, {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  .then(() => {
    app.listen(port, () => {
      console.log(`App running on port ${port}...`);
    });
  })
  .catch(error => console.log(error));

app.post("/user", async (req, res) => {
  let result = await User.create(req.body);
  res.send(result);
});

app.get("/user/:userId", async (req, res) => {
  const result = await User.findById(req.params.userId).populate({
    path: "follows",
    select: "_id username"
  });
  res.send(result);
});

app.post("/user/:userId/follow/:followedUserId", async (req, res) => {
  const result = await User.findByIdAndUpdate(
    req.params.userId,
    {
      $push: {
        follows: req.params.followedUserId
      }
    },
    { new: true }
  );
  res.send(result);
});

app.post("/tweet", async (req, res) => {
  let result = await Tweet.create(req.body);
  res.send(result);
});

app.get("/user/:userId/followedTweets", async (req, res) => {
  const user = await User.findById(req.params.userId);

  const result = await Tweet.find({ userId: { $in: user.follows } });
  res.send(result);
});

首先创建几个用户发送一个POST到这个urlhttp://localhost:3000/user

请求:

{
    "username": "username1"
}

然后使用此 url 将关注者添加到给定用户:

http://localhost:3000/user/5ddfdfaf8c62b141146cbcff/follow/5ddfdfd18c62b141146cbd02

这意味着 ID 为 5ddfdfaf8c62b141146cbcff 的用户关注用户 5ddfdfd18c62b141146cbd02

此时您可以让用户及其关注的用户向该网址发送GET 请求:

http://localhost:3000/user/5ddfdfaf8c62b141146cbcff

响应会是这样的:

{
    "follows": [
        {
            "_id": "5ddfdfbf8c62b141146cbd00",
            "username": "username2"
        },
        {
            "_id": "5ddfdfc78c62b141146cbd01",
            "username": "username3"
        },
        {
            "_id": "5ddfdfd18c62b141146cbd02",
            "username": "username4"
        }
    ],
    "_id": "5ddfdfaf8c62b141146cbcff",
    "username": "username1",
    "__v": 0
}

从这个响应中,我们了解到 username1 跟在 username2、username3 和 username4 之后。

然后您可以创建将POST 发送到此网址的推文:http://localhost:3000/tweet

请求:

{
    "userId": "5ddfdfbf8c62b141146cbd00",
    "tweetText": "user 2 tweet 1"
}

回复:

{
    "_id": "5ddfe1e7911cec475093f623",
    "userId": "5ddfdfbf8c62b141146cbd00",
    "tweetText": "user 2 tweet 1",
    "__v": 0
}

添加几条这样的推文后,您可以发送GET 请求此网址以获取用户关注的用户推文:

http://localhost:3000/user/5ddfdfaf8c62b141146cbcff/followedTweets

响应会是这样的:

[
    {
        "_id": "5ddfe1e7911cec475093f623",
        "userId": "5ddfdfbf8c62b141146cbd00",
        "tweetText": "user 2 tweet 1",
        "__v": 0
    },
    {
        "_id": "5ddfe20a911cec475093f624",
        "userId": "5ddfdfbf8c62b141146cbd00",
        "tweetText": "user 2 tweet 2",
        "__v": 0
    },
    {
        "_id": "5ddfe22b911cec475093f625",
        "userId": "5ddfdfc78c62b141146cbd01",
        "tweetText": "user 3 tweet 1",
        "__v": 0
    }
]

【讨论】:

  • 一切正常,除了最后一个查询显示用户关注的其他人的一系列推文。即使在关注并为其他用户添加推文之后,我也会得到一个空数组
  • @NawazMoinyaakuza 你确定你使用的是正确的用户 ID 吗?因为我测试了这段代码。
  • @NawazMoinyaakuza 您是否创建了用户关注的用户推文?
  • router.route('/:userId/followedTweets').get((req,res)=>{ const user=User.findById(req.params.userId); Tweet.find({userId:{$in:user.follows}}) .then(followersData=>res.json(followersData)) .catch(err=>res.status(400).json("Error:"+err)) })
  • @NawazMoinyaakuza 确保您正确创建文档,您是否为用户创建了推文?
【解决方案2】:

您可以使用聚合来实现您的特定结果。 就像你有 2 个集合,first_collection 和 second_colleciton。

db.getCollection('first_collecition').aggregate([
{
        "$facet":{
            "tweets":[
                "$lookup":{
                    "from":"second_collection",
                    "localField":"userId1",
                    "foreignField":"userId",
                    "as":"tweets"
                },
                {
                    "$project":{
                        "userId":"$userId",
                        "tweets":"tweetText"
                    }
                }
            ]
        }
    }

])

【讨论】:

    猜你喜欢
    • 2016-09-27
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多