0

I am building a boat visualizer using AISHub APIs. After inquiring the APIs I am able to obtain a json file with the vessels and filter with only the vessel I am interested in, and inject them into a table on the webpage. The API gives the following fileds: [NAME, MMSI, LONGITUDE, LATITUDE]. I can correctly connect to MongoDB as I npm start.

The problem: I would like to send also this data to a collection in to MongoDB database every 5 minutes. I tried many different way to do that, but none of them seems to be working.

It was very difficult to think which parts of the code to pass and which not, but below I believe there are enough information to understand what the problem is:

app.js is where I set the MongoDB connection

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var mongoose = require('mongoose');
const bodyParser = require('body-parser');
const vesselController = require('./controllers/VesselController');
require('./config/keys');

var app = express();
app.use(cors());
app.options('*', cors());

// DB Config
const db = require('./config/keys').MongoURI;

const options = {
    useNewUrlParser: true,
    reconnectTries: Number.MAX_VALUE,
    poolSize: 10
};

mongoose
    .connect(db, options)
    .then(() => console.log('MongoDB Connection established'))
    .catch((err) => console.log('Error connecting MongoDB database due to: ', err));

const PORT = process.env.PORT || 3000;

app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(cors());

app.route('/vessels/all').get(vesselController.getBaseAll);
app.route('vessels/:id/track').get(vesselController.getCurrent);
app.route('/vessels').get(vesselController.getHistory);

app.listen(PORT, console.log(`Server started on port ${PORT}`));

module.exports = app;

index.js is where I am caching the data (and where I think the app should send data to MongoDB)

var express = require('express');
var router = express.Router();
var axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();

let hitCount = 0;

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

const mmsiOfInterest = [
    '367029520', 
    '366909730', 
    '367128570'
];

const shipNamesOfInterest = [
    'MICHIGAN',
    'JP BOISSEAU',
    'DELAWARE BAY'
];

router.get('/hello', async function(req, res, next) {

    const allData = myCache.get('allData');

    if (!allData) {
        hitCount++;
        console.log(`hit ${hitCount} number of times`);
        const { data } = await axios.get(
            'http://data.aishub.net/ws.php?username=KEY&format=1&output=json&compress=0&latmin=11.42&latmax=58.20&lonmin=-134.09&lonmax=-52.62'
        );
        const [ metaData, ships ] = data;
        console.log(data);

        const shipsOfInterest = ships.filter(
            (ship) => mmsiOfInterest.includes(ship.MMSI) || shipNamesOfInterest.includes(ship.NAME)
        );
        myCache.set('allData', shipsOfInterest, 70);
        res.send(data);
        return;
    }
    res.send(allData);
});

module.exports = router;

VesselController.js: is where I have the functions for getting different information such as currect vessel, all vessels, history of vessels

module.exports.getBaseAll = (req, res) => {
    Promise.all([
        Compnanies.find(),
        Vessels.find(),
        Positions.aggregate([
            {
                $sort: {
                    date: -1
                }
            },
            {
                $group: {
                    _id: '$callsign',
                    details: {
                        $push: '$$ROOT'
                    }
                }
            },
            {
                $replaceRoot: {
                    newRoot: {
                        $arrayElemAt: [ '$details', 0 ]
                    }
                }
            }
        ])
    ])
        .then(([ companies, vessels, positions ]) => {
            // apply vessels detail table as join:
            positions.forEach((pos) => {
                vessels.forEach((ves) => {
                    if (pos.callsign == ves.callsign) {
                        p._detail = ves;
                    }
                });
                companies.forEach((com) => {
                    if (p._detail.company == com.number) {
                        p._detail = com;
                    }
                });
            });
            res.status(200).json(positions);
        })
        .catch((err) => {
            return res.status(500).send(err);
        });
    console.log(vesselController.getBaseAll);
};

module.exports.getHistory = (req, res) => {
    var id = req.param.id;
    Positions.find(
        {
            callsign: id,
            date: {
                $gte: new Date(Date.now() - 1000 * 60 * 60 * 24)
            }
        },
        (err, task) => {
            if (err) {
                return res.status(500).send(err);
            }
            res.status(200).json(task);
        }
    );
    console.log(vesselController.getHistory);
};

module.exports.getCurrent = (req, res) => {
    var currentPos = Positions.find({
        date: {
            $gte: new Date(Date.now() - 1000 * 60 * 60)
        }
    });
    currentPos.exec((err, task) => {
        if (err) {
            return res.status(500).send(err);
        }
        res.status(200).json(task);
    });
    console.log(vesselController.getCurrent);
};

In LatitudeLongitude.js I set the proper format according to MongoDB documentation

const mongoose = require('mongoose');

const LatitudeLongitudeSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    mmsi: {
        type: Number,
        required: false
    },
    longitude: {
        type: Number,
        required: false
    },
    latitude: {
        type: Number,
        required: false
    }
});

const LatitudeLongitude = mongoose.model('LatitudeLongitude', LatitudeLongitudeSchema);
module.exports = LatitudeLongitude;

users.js is where I set the router.post

var express = require('express');
var router = express.Router();

const LatitudeLongitude = require('../models/LatitudeLongitude');

/* GET users listing. */
router.get('/', function(req, res, next) {
    res.send('respond with a resource');
});

router.post('/vessles/map', function(req, res) {
    const { name, mmsi, longitude, latitude } = req.body;
    let errors = [];

    // Check required fields
    if (!name || !mmsi || !longitude || !latitude) {
        errors.push({ msg: 'No data received' });
    }
    if (
        LatitudeLongitude.findOne({ mmsi: mmsi }).then((pos) => {
            if (pos) {
                // vessel exists
                const newVessel = new Vessles({
                    name,
                    mmsi,
                    longitude,
                    latitude
                });
            }
        })
    );
});

module.exports = router;

Below the collection set inside MongoDB, which is clearly empty:

trackerdb

How can I successfully pass information from the API I mentioned above, into my MongoDB?

What I have donbe so far:

I tried many different ways to pass data from the API to MongoDB every 5 minutes. Among the dirfferent approaches, the one I included in this post are, I think, the most effective, however there is something missing I can't catch/understand.

I believe that the file index.js should be the one that is in charge of taking care of doing that, as I pre-set all the check in that file. However I am now confused whether that is the right location or not. the reasons why you see the routes as app.route('/vessels/all').get(vesselController.getBaseAll); in the app.js file is because I will use that as end point api check with Postman once everything is working. I figured I would leave it there so you see how I designed the process.

Thanks for shedding light on this matter.

1 Answer 1

2

In my opinion, you should first test my approach by attaching following code to your server.js file. then refactor it

setInterval( () => { fetch('http://your/get/route'). then( updateDB() ). catch(doWhateverYouWant()); },3000 );

Sign up to request clarification or add additional context in comments.

1 Comment

Hello and thanks for reading the question. I don't have a server.js file in my application. Could you please explain your answer? Could you include your code into the file I need to modify? That would help me understand your suggestion :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.