I am building a boat visualizer using AISHub APIs . After inquiring the APIs I am able to obtain a json file with thousands of vessels, but I filter only the vessels I am interested in, and inject them into a table on a webpage. The API gives the following fileds: [NAME, MMSI, LONGITUDE, LATITUDE, others...]
. The most important parameters I am using for the filtering are : NAME
and MMSI
(whereas there could be multiple vessels with same NAME
, there cannot be two vessels with the same MMSI
number because it is unique).
The problem I have is that the filter
function does not seem to have the proper behavior. In fact it does not filter uniquely for that specific NAME
and/or MMSI
and I end up having multiple vessels with same NAME
and with different MMSI
. Also the vessel that should appear, it does not, despite I hard-coded the NAME
and MMSI
for that specific vessel. Which is not explainable as I hard-coded those numbers to be specifically filtered.
Below the code I am using for the filtering search:
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', // ok -> MICHIGAN
'366909730', // ok -> JP BOISSEAU
'367128570', // ok -> DELAWARE BAY
'366744010', // ok -> ATLANTIC SALVOR
// Other MMSI numbers .....
];
const shipNamesOfInterest = [
'MICHIGAN',
'JP BOISSEAU',
'DELAWARE BAY',
'ATLANTIC SALVOR',
// Other NAMES....
]
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=MY_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;
}
console.log('this is the data:', allData);
res.send(allData);
});
module.exports = router;
Also below a typical JSON
response from the API:
{"MMSI":225342000,"TIME":"2020-01-26 01:45:48 GMT","LONGITUDE":1.43912,"LATITUDE":38.91523,"COG":339.9,"SOG":0,"HEADING":297,"ROT":0,"NAVSTAT":0,"IMO":9822449,"NAME":"ILLETAS JET","CALLSIGN":"EAVX","TYPE":40,"A":4,"B":25,"C":4,"D":4,"DRAUGHT":0,"DEST":"IBIZA","ETA":"00-00 00:00"}
What I have done so far:
1) I tried different combination with the filter
function and I tried to filter by MMSI
, which is supposed to be unique for each vessel, but still I end up with vessels with same NAME
and different MMSI
(despite I hard-coded the MMSI
...I don't understand):
const shipsOfInterest = ships.filter(
(ship) => mmsiOfInterest.includes(ship.MMSI)
);
After I tried filtering by NAME
, but that does not work either:
const shipsOfInterest = ships.filter(
(ship) => shipNamesOfInterest.includes(ship.NAME)
);
EDIT 2
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'
);
// console.log(data);
const { metaData, ships } = data;
const set = new Set();
const shipsOfInterest = ships.filter((ship) => {
if (set.has(ship.MMSI)) return false;
set.add(ship.MMSI);
return true;
});
myCache.set('allData', shipsOfInterest, 70);
res.send(data);
return;
}
console.log('this is the data:', allData);
res.send(allData);
});
module.exports = router;
Below the error:
I don't know if the filter
function can get a better result if organized in a different way. I thought that this could have been a very good way to organize the search and don't understand what it does not work. Thanks for pointing to the right direction for solving this issue.
I guess you made mistake while using the shorthand assignment. Use {} instead of [].
Instead of:
const [ metaData, ships ] = data;
try:
const { metaData, ships } = data;
In the end of if
statement you do res.send(data)
, which is basically the data you received from the API. Instead, you need to res.send(shipsOfInterest)
; Also, change the format of mmsiOfInterest
list from strings to numbers, because you receive numbers from the API.
So, as far as I understand you the filtered list to contain the records with unique MMSI
value. So, what you need to do is:
const uniqueMMSI = new Set();
const shipsOfInterest = ships.filter(
(ship) => {
if (set.has(ship.MMSI)) return false;
set.add(ship.MMSI);
return true;
}
);
I hope I understood your question :)
It looks like MMSI is coming in as a numeric value, while your comparison array is holding strings. How about using an array of integers for your comparison?
const mmsiOfInterest = [
367029520,
366909730,
367128570,
366744010,
// Other MMSI numbers .....
];
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.