Пн goose: создание динамического индекса c для вложенного документа при обновлении существующего документа - PullRequest
0 голосов
/ 09 марта 2020

Я работаю с коллекцией бесед, которая содержит несколько сообщений.

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

(идентификаторы документов в приведенных ниже примерах заменены для краткости).


Что я пытаюсь получить после отправки нескольких сообщений в документ беседы:

// conversation document

{
  _id: "C1",
  messageCount: 3,
  lastMessage: { sender: "U2", content: "I am Stephen", messageIndex: 3 },
  messages: [
    { sender: "U1", content: "Hello", messageIndex: 0 },
    { sender: "U1", content: "I'm Bob", messageIndex: 1 },
    { sender: "U2", content: "Hi there!", messageIndex: 2 },
    { sender: "U2", content: "I am Stephen", messageIndex: 3 }
  ]

}


Что я получаю:

// conversation document

{
  _id: "C1",
  messageCount: 3,
  lastMessage: { sender: "U2", content: "I am Stephen", messageIndex: 0 },
  messages: [
    { sender: "U1", content: "Hello", messageIndex: 0 },
    { sender: "U1", content: "I'm Bob", messageIndex: 0 },
    { sender: "U2", content: "Hi there!", messageIndex: 0 },
    { sender: "U2", content: "I am Stephen", messageIndex: 0 }
  ]
}


Мне интересно, возможно ли каким-то образом динамически увеличивать поле для каждого нового созданного вложенного документа (путем выполнения одного запроса на обновление).

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


Мой подход состоял в том, чтобы попытаться сослаться на значение из существующего (родительский) документ.


Это мой запрос на обновление, где я пу sh новое сообщение в поле messages.

const addNewMessage = async (conversationId, contentStr, userId) => {

  const message = { content: contentStr, sender: userId  }

  const updated = await ConversationModel.findOneAndUpdate(
    { _id: conversationId },
    {
      $push: { messages: message },
      $inc: { messageCount: 1 },
      lastMessage: message
    },
    { new: true }
  );

  return updated;
};



Это моя модель с подсхемой.

conversation-model.js
import mongoose from "mongoose";
const { Schema } = mongoose;


// sub schema
const Message = new Schema(
  {
    sender: ObjectId,
    content: String,
    messageIndex: {
      type: Number,
      default: function() {
        console.log('\n this: ', this);
        if (!this.messageCount) return 0;
        else return this.messageCount;
  // if `messageCount` is 0 or not set, set the message index to `0` - first message
  // else set the `messageIndex` using the `messageCount` from the conversation document
      }
    }
  }
);



// Conversation Model
const conversationSchema = new Schema(
  {
    messageCount: { type: Number, min: 1 },
    lastMessage: Message,
    messages: [ Message ]
  }
);


const Conversation = mongoose.model("Conversation", conversationSchema);

module.exports = Conversation;


Я мог бы сначала получить документ беседы через findById(), а затем использовать .save(), чтобы запустить обновление и вставить новое сообщение.
Однако мне интересно, есть ли способ сделать это, запустив только один запрос на обновление?


...