0

I am trying to build a music app and while working on the back end for the app (using express), I am facing this weird issue of documents not saving in mongo collections.

I made a post route to which user submits form data, which contains the song's mp3 file and the name of the song (it will have more data later on).

I am using multer to parse multipart form data. I am able to save the mp3 file to mongoDB using multer-gridfs-storage. I want to save the song info such as name, artists etc in a different collection and here is the schema for the collection:

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 file:

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,
    });
  });
});

On line (*) the server just freezes until the request gets timed out. No errors shown on console. Don't know what to do :(

2 Answers2

0

I solved the issue finally! So what i did was bring the models in index.js file and changed up some stuff here and there..

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');
      }
    });
  });
});

At line (***) I used the same instance of mongoose that was initialized.. in the previous file I imported it again from the package...

0

Kia ora!

For those stumbling here three years on. I came across this issue as well. Abhishek Mehandiratta has the answer hidden in their code snippet.

The Fix
I went from instantiating mongoose with:

connect(connStr)

to doing:

const conn = createConnection(connStr)

This is the breaking change. So for an easy fix, change your code back to using connect(...).
I too, followed the documentation and Youtube tutorials to alter my code in such a way. It's an unfortunate misleading for developers who have not encountered a need to understand the difference.

I changed it back, and now it's working again (even with 'multer-gridfs-storage'). You can reference the connection with:

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

Why is this happening?
BenSower writes up the differences between connect and createConnection here. So from my basic understanding of BenSower's write up, you're referencing the wrong connection pool when you create your 'Song' schema, and thus, referencing the wrong pool when saving. I guess this results in a time out, have not looked further, but I'm sure a more in-depth answer exists somewhere.

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

As BenSower states in their answer "For me, the big disadvantage of creating multiple connections in the same module, is the fact that you can not directly access your models through mongoose.model, if they were defined "in" different connections". They're spot on with this one. Having finally overcome this obstacle, I shall have a look into createConnection on another project. For now, good ol' connect() will fix this issue, and do just fine :D