Mongoose save() не работает при помещении документов в коллекцию и загрузке файлов с помощью multer-gridfs-storage

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

Я сделал пост-маршрут, по которому пользователь отправляет данные формы, которые содержат mp3-файл песни и название песни (позже у нее будет больше данных).

Я использую multer для разбора данных из нескольких частей. Я могу сохранить mp3-файл в mongoDB, используя multer-gridfs-storage. Я хочу сохранить информацию о песне, такую ​​как имя, исполнители и т. Д. В другой коллекции, и вот схема для коллекции:

import mongoose from 'mongoose';

const Schema = mongoose.Schema;

const SongsInfo = new Schema({
   name: {
     type: String,
     required: true,
   },
});

const Song = mongoose.model('Song', SongsInfo);
export default Song;

Файл index.js:

import Grid from 'gridfs-stream';
import GridFsStorage from 'multer-gridfs-storage';

const app = express();
const conn = mongoose.createConnection(mongoURI);

let gfs;

conn.once('open', () => {
  console.log('Connected to mongodb');
  gfs = Grid(conn.db, mongoose.mongo);
  gfs.collection('songFiles');
});

// storage engine
const storage = new GridFsStorage({
  url: mongoURI,
  file: (req, file) => new Promise((resolve, reject) => {
    crypto.randomBytes(16, (err, buf) => {
      if (err) {
        return reject(err);
      }
      const filename = buf.toString('hex') + 
             path.extname(file.originalname);
      let fileInfo;

    fileInfo = {
      filename,
      bucketName: 'songFiles',
    };

      resolve(fileInfo);
    });
  }),
});
let upload;

middleWare(app);

app.post('/api/uploadSong', async (req, res) => {
  upload = multer({ storage }).any();

  upload(req, res, async (err) => {
    console.log('in');
    if (err) {
      // console.log(err);
      return res.end('Error uploading file.');
    }
    const { name } = req.body;
    // push a Song into songs collection
    const songInfo = new Song({
      name,
    });
    const si = await songInfo.save();    // (*)
    console.log(songInfo);
    res.json({
      songInfo: si,
      file: req.file,
    });
  });
});

В строке (*) сервер просто зависает до истечения времени ожидания запроса. На консоли не отображаются ошибки. Не знаю что делать:(

2 ответа

Я наконец решил проблему! Так что я сделал, привел модели в файл index.js и кое-что изменил.

index.js

const app = express();
mongoose.connect(mongoURI); //(*)
const conn = mongoose.connection; // (*)

let gfs;

conn.once('open', () => {
  console.log('Connected to mongodb');
  gfs = Grid(conn.db, mongoose.mongo);
  gfs.collection('songFiles');
});

// models
const Schema = mongoose.Schema; //(***)

const SongsInfo = new Schema({
  name: {
    type: String,
    required: true,
  },
});

const Song = mongoose.model('Song', SongsInfo);

// storage engine
const storage = new GridFsStorage({
  url: mongoURI,
  file: (req, file) => new Promise((resolve, reject) => {
    crypto.randomBytes(16, (err, buf) => {
      if (err) {
        return reject(err);
      }
      const filename = buf.toString('hex') + path.extname(file.originalname);
      let fileInfo;
      if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
        fileInfo = {
          filename,
          bucketName: 'imageFiles',
        };
      } else {
        fileInfo = {
          filename,
          bucketName: 'songFiles',
        };
      }
      resolve(fileInfo);
    });
  }),
});
let upload;

middleWare(app);

app.post('/api/uploadSong', async (req, res) => {
  upload = multer({ storage }).any();

  upload(req, res, async (err) => {
    console.log('in');
    if (err) {
      return res.end('Error uploading file.');
    }
    const { name } = req.body;
    // push a Song into songs collection
    const songInfo = new Song({
      name,
    });
    songInfo.save((er, song) => {
      if (!er) {
        res.send('err');
      } else {
        console.log(err, song);
        res.send('err');
      }
    });
  });
});

В строке (***) я использовал тот же экземпляр mongoose, который был инициализирован.. в предыдущем файле я снова импортировал его из пакета...

Kia ORA!

Для тех, кто споткнулся здесь три года спустя. Я тоже столкнулся с этой проблемой. user8174895 ответ в своем фрагменте кода.

Исправление
, которое я перешел от создания экземпляра мангуста:

      connect(connStr)

делать:

      const conn = createConnection(connStr)

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

Я изменил его обратно, и теперь он снова работает (даже с «multer-gridfs-storage»). Вы можете сослаться на соединение с:

      import {connection} from "mongoose";
connection.once('open', ...)

Почему это происходит?
user2856218 различия между connect и createConnection здесь . Итак, исходя из моего базового понимания написания BenSower, вы ссылаетесь на неправильный пул соединений при создании схемы «Песня» и, следовательно, ссылаетесь на неправильный пул при сохранении. Я предполагаю, что это приводит к тайм-ауту, я не смотрел дальше, но я уверен, что где-то существует более подробный ответ.

       import mongoose from 'mongoose';
const Song = mongoose.model('Song', SongsInfo);

Как заявляет BenSower в своем ответе : «Для меня большим недостатком создания нескольких соединений в одном модуле является тот факт, что вы не можете напрямую получить доступ к своим моделям через mongoose.model, если они были определены «в» разных соединениях» . Они на месте с этим. Наконец-то преодолев это препятствие, посмотрю createConnection на другом проекте. А пока, молодец исправит эту проблему, и все будет хорошо :D

Другие вопросы по тегам