Лучший способ добавления вложенных вложенных документов в mongoDB - PullRequest
1 голос
/ 04 августа 2020

У меня есть пользователь и модель сообщения. Связь следующая: у пользователя может быть много сообщений.

Цель: Я ищу лучший или самый элегантный способ добавить новое сообщение и связать его с соответствующим пользователем .

Модель пользователя:

const UserSchema = new Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  email: {
    type: String,
    required: true,
    unique: true,
  },
  password: {
    type: String,
    required: true,
  },
  register_date: {
    type: Date,
    default: Date.now
  },
  osrs_messages: [OsrsMessage]
});

Модель сообщения:

const OsrsMessageSchema = new Schema({
  message: {
    type: String,
    required: true,
  },
  username: {
    type: String,
    required: true,
    unique: true,
  },
  send_date: {
    type: Date,
    default: Date.now
  }
});

Мой маршрутизатор, который добавляет новое сообщение и добавляет сообщение соответствующему пользователю:

router.post("/osrs", verifyAccessToken, async (req, res) => {
  try {
    const { username, message } = req.body;
    // create a new message and save
    let newMessage = new OsrsMessage({ username, message });
    newMessage = await newMessage.save();
    // get the associated user and add new message to messages array
    let user = await User.findById(req.user.id);
    user.osrs_messages.push({ username, message });
    user = await user.save();
    return res.status(200).json({ message: "message received" });
  } catch (error) {
    console.log("error message:", error);
    return res
      .status(500)
      .json({ message: "Oops... looks like something went wrong" });
  }
});

Есть ли способы улучшить это? Что лучше использовать findOneAndUpdate или insert? Могу ли я автоматически добавить сообщение в свою коллекцию сообщений, если я свяжу его с пользователем, или мне всегда нужно вручную добавлять его в коллекцию?

Ответы [ 2 ]

3 голосов
/ 04 августа 2020

Вместо 2 запросов, findById и .save() вы можете go с 1 запросом updateOne.

router.post("/osrs", verifyAccessToken, async (req, res) => {
  try {
    const { username, message } = req.body;

    // create a new message and save
    let newMessage = new OsrsMessage({ username, message });

    newMessage = await newMessage.save();

    await User.updateOne({_id: req.user.id}, {
       $push: {
          osrs_messages: newMassage._id
       }
    });

    return res.status(200).json({ message: "message received" });

  } catch (error) {
    console.log("error message:", error);
    return res
      .status(500)
      .json({ message: "Oops... looks like something went wrong" });
  }
});
1 голос
/ 04 августа 2020

Вам нужно добавлять сообщения в коллекцию вручную. Но вы можете улучшить свою реализацию, используя Populate

Заполнение - это процесс автоматической замены указанных путей в документе документами из других коллекций

У вас может быть хороший обзор Populate здесь

Основное преимущество использования populate заключается в том, что в коллекции сохраняется ссылка _id документа, и если вам необходимо обновить любой вложенный документ, OsrsMessage в вашем случае, вам не нужно обновлять / повторно вставлять его в User.

Документация заполнить имеет хороший обзор того, как вы можете его использовать. Я надеюсь, что это поможет вам улучшить вашу текущую реализацию.

Вы можете написать таким образом,

const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
register_date: {
type: Date,
default: Date.now
},
osrs_messages: [{ type: Schema.Types.ObjectId, ref: 'OsrsMessage' }]
});

Добавьте в свой код сообщение следующим образом:

router.post("/osrs", verifyAccessToken, async (req, res) => {
try {
const { username, message } = req.body;
// create a new message and save
let newMessage = new OsrsMessage({ username, message });
newMessage = await newMessage.save();
// get the associated user and add new message to messages array
let user = await User.findById(req.user.id);
user.osrs_messages.push(newMessage._id);
user = await user.save();
return res.status(200).json({ message: "message received" });
} catch (error) {
console.log("error message:", error);
return res
  .status(500)
  .json({ message: "Oops... looks like something went wrong" });
}
});

После этого, когда вам нужно получить пользователя с сообщением, вы можете выполнить такой запрос

const user = await User.
    findById(req.user.id).
    populate({ path: 'osrs_messages'}).
    exec();

Здесь вы получите пользователя со всеми osrs_messages в виде списка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...