Almost done ! What’s missing is to save the images in the database and to create express endpoints to recover the images, and the images paginated by tags.

Part 4: MongodDb

To facilitate our queries to the database, we will use an ODM (Object Document Mapper), so, yes, the term can be scary but in fact it is made to make our life easier, it’s called Mongoose.

We will create a folder db to separate from the rest of the code and in db create a model folder, which symbolizes the format of objects existing in the database:

$ mkdir -p db/models

Install Mongoose:

$ npm install --save mongoose

First, create the model :


//content of db/models/image.js
const mongoose = require('mongoose');

// build the schema
const imageSchema = mongoose.Schema({
    path: String,
    tags: [String]
});

// compile the schema into a model
const Image = mongoose.model('Image', imageSchema);

module.exports = Image

Then the connection to the database:


//content of db/index.js
const mongoose = require('mongoose');
const Image = require('./models/image');

// connect the  database
mongoose.connect('mongodb://localhost/images');

module.exports = Image

And finally, the persistence of the data in the api / app.js as well as the routes that will allow us to recover our images:


//content of api/app.js
const express = require('express')
const multer = require('multer')
const clarifay = require('./clarifay')
const fs = require('fs');
const Image = require('../db')

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads')
  },
  filename: (req, file, cb) => {
    cb(null, `${Date.now()}.${file.mimetype.split('/')[1]}`)
  }
})

const upload = multer({ storage })
const app = express()

app.post('/photos/upload', upload.array('photos'), (req, res, next) => {
  const message = { "data": [] }
  req.files.forEach(image => {
    fs.readFile(image.path, function (err, data) {
      // predict the contents of an image by passing in base 64 encoded file
      clarifay
        .analyse(new Buffer(data).toString('base64'))
        .then(
        response => {
          const imageObject = {
            'path': image.path,
            'tags': serialize(response.outputs[0].data.concepts)
          }
          message.data.push(imageObject)
          // save in db
          const imageData = new Image(imageObject)
          imageData.save()
          // if every image has been proccessed send back the response
          if (message.data.length == req.files.length) {
            res.status(200).send(message)
          }
        },
        err => console.error(err)
        );
    });
  })
})

// get all images
app.get('/photos', (req, res, next) => {
  Image.find({}, (err, images) => res.send(images))
})

// get images by tags
app.get('/photos/:tag', (req, res, next) => {
  Image.find({ tags: req.params.tag }, (err, images) => res.send(images))
})

// get the tags from the Clarifay API
const serialize = (array) => {
  let subjects = [];
  array.forEach(function (element) {
    subjects.push(element.name)
  });
  // get only the best of 3 results
  return subjects.slice(0, 3)
}

module.exports = app

It’s done for this series !! You will find the complete code here