Нажмите на массив второго уровня в mongodb с узлом / экспресс

Я работаю в чате, где пользователи могут общаться друг с другом на основе отфильтрованных проектов. Пользователи из одного проекта могут общаться друг с другом.

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

'use strict';
var mongoose = require('bluebird').promisifyAll(require('mongoose'));
var ChatSchema = new mongoose.Schema({
  projectid: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Project'
  },
  messages: [{
    userid: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
    },
    message: String,
    date: {
      type: Date,
      default: Date.now
    },
    time: String
  }]
});
export default mongoose.model('Chat', ChatSchema);

Сейчас я пытаюсь обновить массив сообщений новыми сообщениями, но я не могу сделать это с последних нескольких часов. Вот что у меня так далеко.

Чтобы получать сообщения чата на основе проектов, которые я использую:

маршруты:

router.get('/projectid/:id', controller.showByProject);
router.post('/projectid/:id', controller.insertMessageByProject);

контроллер:

// Gets the chat thread based on project id
export function showByProject(req, res) {
  Chat.findAsync({projectid: req.params.id})
    .then(handleEntityNotFound(res))
    .then(respondWithResult(res))
    .catch(handleError(res));
}

// Insert a new message in the chat based on projectid
export function insertMessageByProject(req, res) {
  if (req.body._id) {
    delete req.body._id;
  }
  Chat.findAsync({projectid: req.params.id})
    .then(handleEntityNotFound(res))
    .then(saveUpdates({$push: {messages: req.body}}))
    .then(respondWithResult(res))
    .catch(handleError(res));
}

Объект Json, который я отправляю от POSTMAN:

{
    "messages": 
    {
      "userid": "56d7967745ab81322a964927",
      "message": "This is a meesage"
    }
}

ИЛИ ЖЕ

{
  "userid": "56d7967745ab81322a964927",
  "message": "This is a meesage"
}

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

Ваша помощь будет высоко ценится.

РЕДАКТИРОВАТЬ 1: вот вспомогательные функции, которые я использую, сгенерированные угловым полнофункциональным плагином.

function respondWithResult(res, statusCode) {
  statusCode = statusCode || 200;
  return function(entity) {
    if (entity) {
      res.status(statusCode).json(entity);
    }
  };
}

function saveUpdates(updates) {
  return function(entity) {
    var updated = _.merge(entity, updates);
    return updated.saveAsync()
      .spread(updated => {
        return updated;
      });
  };
}

function removeEntity(res) {
  return function(entity) {
    if (entity) {
      return entity.removeAsync()
        .then(() => {
          res.status(204).end();
        });
    }
  };
}

function handleEntityNotFound(res) {
  return function(entity) {
    if (!entity) {
      res.status(404).end();
      return null;
    }
    return entity;
  };
}

function handleError(res, statusCode) {
  statusCode = statusCode || 500;
  return function(err) {
    res.status(statusCode).send(err);
  };
}

РЕДАКТИРОВАТЬ 2: Как я уже упоминал в комментариях, проблема была с _.Merge функция, которая не сливала объект правильно, хотя должна была иметь возможность обновить объект.

Поэтому я написал свою собственную функцию для saveUpdates следующим образом:

function saveUpdatesForNewChat(updates) {
  return function(entity) {

    var temp = entity;
    temp[0].messages.push(updates);

    console.log('\ntemp:');
    console.log(require('util').inspect(temp, { depth: null }));
    console.log('\nend of ops\n\n');

    var updated = _.merge(entity, temp);
    console.log('out of merge');
    console.log(require('util').inspect(updated, { depth: null }));
    return updated.saveAsync()
      .spread(updated => {
        return updated;
      });
  };
}

Итак, я оставил внутри консольные журналы, и это идеальный объект для сохранения в базе данных, но сервер все равно возвращает 500 ошибок при обновлении.

1 ответ

Решение

ХОРОШО! Так что я нашел ответ сам.

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

Вот код:

function saveUpdatesForNewChat(updates) {
  return function(entity) {
    var temp = entity[0];
    temp.messages.push(updates);
    var updated = temp;
    return updated.saveAsync()
      .spread(updated => {
        return updated;
      });
  };
}
Другие вопросы по тегам