首页 > 解决方案 > 如何将 API 数据动态传递给 MongoDB 数据库

问题描述

我正在使用AISHub API 构建一个小船可视化器。查询 API 后,我可以获取包含容器的 json 文件,并仅使用我感兴趣的容器进行过滤,并将它们注入网页上的表格中。API 提供以下文件: [NAME, MMSI, LONGITUDE, LATITUDE]. 我可以正确连接到MongoDBnpm start

问题:我还想MongoDB每 5 分钟将这些数据发送到数据库中的集合。我尝试了许多不同的方法来做到这一点,但它们似乎都没有奏效。

很难考虑代码的哪些部分通过,哪些不通过,但我相信下面有足够的信息来理解问题所在:

app.js是我设置MongoDB连接的地方

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是我缓存数据的地方(以及我认为应用程序应该将数据发送到的地方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:我拥有获取不同信息的功能,例如当前船只、所有船只、船只历史

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

LatitudeLongitude.js我根据MongoDB文档设置了正确的格式

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是我设置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;

在里面的集合集合下面MongoDB,显然是空的:

跟踪数据库

我怎样才能成功地将上面提到的 API 中的信息传递到我的MongoDB?

到目前为止我所拥有的:

我尝试了许多不同的方法来将数据从 API 传递到MongoDB每 5 分钟一次。在不同的方法中,我认为我在这篇文章中包含的方法是最有效的,但是缺少一些我无法捕捉/理解的东西。

我相信文件index.js应该是负责执行此操作的文件,因为我预先设置了该文件中的所有检查。但是,我现在很困惑这是否是正确的位置。app.route('/vessels/all').get(vesselController.getBaseAll);您在app.js文件中看到路由的原因是,Postman一旦一切正常,我将使用它作为端点 api 检查。我想我会把它留在那里,这样你就可以看到我是如何设计这个过程的。

感谢您阐明此事。

标签: javascriptnode.jsreactjsmongodb

解决方案


在我看来,您应该首先通过将以下代码附加到您的 server.js 文件来测试我的方法。然后重构它

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


推荐阅读