node + express 搭建后端服務(wù),連接 mysql 數(shù)據(jù)庫,存入 geojson 數(shù)據(jù)

建立mysql數(shù)據(jù)庫

登錄mysql后眨猎,創(chuàng)建一個(gè)新庫。我的庫名是geometry强经。
通過osm獲得的poi信息切出上海楊浦區(qū)部分輸出為geojson睡陪。
通過如下代碼將geojson數(shù)據(jù)存入

/*
 * @Author: citrusrlia@foxmail.com
 * @FilePath: \shy-node-back\writeJsonInsert.js
 * @Date: 2021-05-24 11:21:32
 * @Description: geojson數(shù)據(jù)入庫
 */
const mysql = require("mysql");
const fs = require("fs");

let result = fs.readFileSync("./statics/yangpu_poi.json"); //osm數(shù)據(jù)
let data = JSON.parse(result.toString());
let ready = data.features;

const connection = mysql.createConnection({
  host: "localhost",
  user: "************",
  password: "*************",
  database: "************",
  port: "6326",
});

connection.connect();
let AddParam = [];
for (let i = 0, l = ready.length; i < l; i++) {
  let osm_id = ready[i].properties.osm_id,
    type = ready[i].geometry.type,
    coordinateStr = ready[i].geometry.coordinates.toString(),
    code = ready[i].properties.code,
    fclass = ready[i].properties.fclass,
    name = ready[i].properties.name;
  AddParam = [osm_id, type, coordinateStr, code, fclass, name];
  connection.query(
    "INSERT INTO geometry(osm_id,type,coordinates,code,fclass,name) VALUES(?,?,?,?,?,?)",
    AddParam,
    function (error, results) {
      if (error) {
        console.log("INSERT ERROR - ", error.message);
        return;
      }
      console.log("INSERT ID:", results);
    }
  );
}

connection.end();

這里將經(jīng)緯度數(shù)據(jù)轉(zhuǎn)化為字符串存儲(chǔ),部分長度會(huì)超過255字節(jié)限制匿情,字段類型需要改為長文本類型兰迫。


image.png

現(xiàn)在獲得了儲(chǔ)存了geojson數(shù)據(jù)的表。

使用express框架搭建服務(wù)

首先安裝express和express腳手架

npm i express
npm i express-generator

運(yùn)行 建立名叫app的項(xiàng)目 會(huì)得到如下圖的目錄結(jié)構(gòu)

express app
image.png

先在public/javascripts中新建sqls.js 用module.exports輸出各增刪改查方法

/*
 * @Author: citrusrlia@foxmail.com
 * @FilePath: \app\public\javascripts\sqls.js
 * @Date: 2021-05-24 15:01:08
 * @Description: 對(duì)數(shù)據(jù)庫的操作
 */
const mysql = require("mysql");
const connection = mysql.createConnection({
  host: "localhost",
  user: "*******",
  password: "***********",
  database: "*************",
  port: "6326",
});

function addItem(params, callback) {
  let sql = `INSERT INTO geometry(osm_id,type,coordinates,code,fclass,name,id) VALUES(?,?,?,?,?,?,?)`;
  let AddParam = [
    params.osm_id,
    params.type,
    params.coordinates,
    params.code,
    params.fclass,
    params.name,
    params.id,
  ];
  connection.query(sql, AddParam, function (err, result) {
    if (err) {
      console.log("Add Geometry ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function deleteByName(name, callback) {
  let sql = `DELETE FROM geometry where name=?`;
  connection.query(sql, [name], function (err, result) {
    if (err) {
      console.log("Delete Geometry ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function editById(params, id, callback) {
  let sql = `UPDATE geometry SET osm_id=?,type=?,coordinates=?,code=?,fclass=?,name=?,id=? where osm_id=? or id=?`;
  let UpdateParam = [
    params.osm_id,
    params.type,
    params.coordinates,
    params.code,
    params.fclass,
    params.name,
    params.id,
  ];
  connection.query(sql, [...UpdateParam, id, id], function (err, result) {
    if (err) {
      console.log("UPDATE Geometry ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function pagination(thispage, pages, callback) {
  let sql = `SELECT * from geometry limit ${(thispage - 1) * pages},${pages}`;
  connection.query(sql, function (err, result) {
    if (err) {
      console.log("pagination ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function getByClass(fclass, callback) {
  let sql = `SELECT * FROM geometry WHERE fclass = ?`;
  connection.query(sql, [fclass], function (err, result) {
    if (err) {
      console.log("GET By class ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function getById(id, callback) {
  let sql = `SELECT * FROM geometry WHERE id = ? or osm_id=?`;
  connection.query(sql, [id, id], function (err, result) {
    if (err) {
      console.log("GET By ID ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function getByName(name, callback) {
  let sql = `SELECT * FROM geometry WHERE name = ?`;
  connection.query(sql, [name], function (err, result) {
    if (err) {
      console.log("GET By Name ERROR - ", err.message);
      return;
    }
    callback(result);
  });
}

function getAllFclass(callback) {
  let sql = `SELECT fclass FROM geometry`;
  connection.query(sql, function (err, result) {
    if (err) {
      console.log("GET ALL CLASS ERROR - ", err.message);
      return;
    }
    let arr = [];
    for (let i = 0, l = result.length; i < l; i++) {
      if (!arr.includes(result[i].fclass)) {
        arr.push(result[i].fclass);
      }
    }
    callback(arr);
  });
}

function getByPosition(initPoint, range, jsonUrl) {
  try {
    initPoint = eval(initPoint + "http://@ sourceURL=initpoint"); //便于調(diào)試eval代碼
    let result = fs.readFileSync(jsonUrl);
    let data = JSON.parse(result.toString());
    let Arr = [];
    for (let i = 0, l = data.features.length; i < l; i++) {
      let center = data.features[i].geometry.coordinates[0].reduce(
        (acc, cur, index, array) => {
          let lng = acc[0] + cur[0],
            lat = acc[1] + cur[1];
          if (index === array.length - 1) {
            return [lng / array.length, lat / array.length];
          }
          return [lng, lat];
        },
        [0, 0]
      );
      let distance = caculateLL(center, initPoint);
      if (distance < range) {
        Arr.push(data.features[i]);
      }
    }
    return Arr;
  } catch (err) {
    console.log(err);
  }
}
/**
 * @author: citrusrlia@foxmail.com
 * @description: 計(jì)算兩點(diǎn)間距離
 * @param {p1,p2 : Arr}
 * @return {number}
 */
function caculateLL(p1, p2) {
  let lat1 = p1[0],
    lng1 = p1[1],
    lat2 = p2[0],
    lng2 = p2[1];
  var radLat1 = (lat1 * Math.PI) / 180.0;
  var radLat2 = (lat2 * Math.PI) / 180.0;
  var a = radLat1 - radLat2;
  var b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0;
  var s =
    2 *
    Math.asin(
      Math.sqrt(
        Math.pow(Math.sin(a / 2), 2) +
          Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)
      )
    );
  s = s * 6378.137;
  s = Math.round(s * 10000) / 10;
  return s;
}

function getAll(callback) {
  // connection.connect();
  let sql = "SELECT * FROM geometry";
  connection.query(sql, function (err, result) {
    if (err) {
      console.log("GETALL ERROR - ", err.message);
      return;
    }
    callback(result);
  });
  // connection.end();
}

module.exports = {
  addItem,
  deleteByName,
  editById,
  pagination,
  getByClass,
  getById,
  getByName,
  getAllFclass,
  getByPosition,
  getAll,
};

接著修改路由index.js炬称,在請求對(duì)應(yīng)地址時(shí)返回對(duì)應(yīng)sql結(jié)果汁果。node-mysql查詢結(jié)果無法通過return返回,需要傳入回調(diào)函數(shù)在回調(diào)中做res.send()玲躯,返回結(jié)果据德。views中頁面使用pug編寫,可以通過修改app.set("view engine","html")改成html語言或其他語言跷车。使用require引入sqls.js時(shí)棘利,項(xiàng)目未編譯,如下設(shè)置不會(huì)使index.js中 ./ 路徑映射到根目錄下朽缴。

app.use(express.static(path.join(__dirname, "public")));
var express = require("express");
var router = express.Router();
var sqls = require("../public/javascripts/sqls");
var url = require("url")

/* 展示views中地址 */
router.get("/", function (req, res, next) {
  res.render("index", { title: "Hello,簡書的朋友!" });
});

router.get("/getByClass", function (req, res) {
  /**
   * @description: 根據(jù)類別查詢對(duì)應(yīng)條目
   * @param {類別:fclass}
   * @return {Array}
   */
  let params = url.parse(req.url, true).query;
  sqls.getByClass(params.fclass, (searchResult) => {
    res.send(searchResult);
  });
});

router.get("/getById", function (req, res) {
  /**
   * @author: citrusrlia@foxmail.com
   * @description: 根據(jù)osm_id查找對(duì)應(yīng)條目
   * @param {String:osm_id}
   * @return {Object}
   */
  let params = url.parse(req.url, true).query;
  sqls.getById(params.id, (searchResult) => {
    res.send(searchResult);
  });
});

router.get("/getByName", function (req, res) {
  /**
   * @author: citrusrlia@foxmail.com
   * @description: 根據(jù)名稱查找對(duì)應(yīng)條目
   * @param {String:name}
   * @return {Arr}
   */
  let params = url.parse(req.url, true).query;
  sqls.getByName(params.name, (result) => {
    res.send(result);
  });
});

router.get("/pagination", function (req, res) {
  /**
   * @description: 分頁查詢對(duì)應(yīng)條目
   * @param {查詢頁標(biāo)page,每頁條目數(shù)perpage}
   * @return {Array}
   */
  let params = url.parse(req.url, true).query;
  sqls.pagination(params.page, params.perpage, (searchResult) => {
    res.send(searchResult);
  });
});

router.post("/addItem", function (req, res) {
  /**
   * @description: 添加條目
   * @param {addData:Object}
   * @return {nothing}
   */
  let params = url.parse(req.url, true).query;
  sqls.addItem(params, (searchResult) => {
    if (searchResult) res.send("添加成功");
  });
});

router.post("/delectByName", function (req, res) {
  /**
   * @description: 刪除條目
   * @param {條目名稱:name}
   * @return {nothing}
   */
  let params = url.parse(req.url, true).query;
  sqls.delectByName(params.name, (searchResult) => {
    if (searchResult) res.send("刪除成功");
  });
});

router.post("/editById", function (req, res) {
  /**
   * @description: 修改條目
   * @param {params:Object,條目名稱:searchId}
   * @return {Array}
   */
  let params = url.parse(req.url, true).query;
  sqls.editById(params, params.searchId, (searchResult) => {
    if (searchResult) res.send("修改成功");
  });
});

router.get("/getAllFclass", function (req, res) {
  /**
   * @author: citrusrlia@foxmail.com
   * @description:獲取所有fclass
   * @param {nothing}
   * @return {Arr}
   */
  let params = url.parse(req.url, true).query;
  sqls.getAllFclass((searchResult) => {
    res.send(searchResult);
  });
});

router.get("/getByPosition", function (req, res) {
  /**
   * @author: citrusrlia@foxmail.com
   * @description:獲取點(diǎn)附近features
   * @param {initPoint:[lng,lat] ,range:number}
   * @return {Arr}
   */
  let params = url.parse(req.url, true).query;
  sqls.getByPosition(params.initPoint, params.range, (searchResult) => {
    res.send(searchResult);
  });
});

router.get("/getAll", function (req, res) {
  /**
   * @author: citrusrlia@foxmail.com
   * @description: 獲取所有features
   * @param {}
   * @return {Arr}
   */
  let params = url.parse(req.url, true).query;
  sqls.getAll((searchResult) => {
    res.send(searchResult);
  });
});
module.exports = router;

調(diào)用

image.png

訪問對(duì)應(yīng)端口善玫,成功拿到數(shù)據(jù)庫中數(shù)據(jù)。

總結(jié)

由于本人系gis前端工程師密强,第一次自己做后端服務(wù)茅郎,文中不足之處希望在看本文的朋友多多留言指正,萬分感謝或渤!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末只洒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子劳坑,更是在濱河造成了極大的恐慌毕谴,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件距芬,死亡現(xiàn)場離奇詭異涝开,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)框仔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門舀武,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人离斩,你說我怎么就攤上這事银舱”衲洌” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵寻馏,是天一觀的道長棋弥。 經(jīng)常有香客問我,道長诚欠,這世上最難降的妖魔是什么顽染? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮轰绵,結(jié)果婚禮上粉寞,老公的妹妹穿的比我還像新娘。我一直安慰自己左腔,他們只是感情好唧垦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著液样,像睡著了一般业崖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓄愁,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天双炕,我揣著相機(jī)與錄音,去河邊找鬼撮抓。 笑死妇斤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的丹拯。 我是一名探鬼主播站超,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乖酬!你這毒婦竟也來了死相?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤咬像,失蹤者是張志新(化名)和其女友劉穎算撮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县昂,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肮柜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倒彰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片审洞。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖待讳,靈堂內(nèi)的尸體忽然破棺而出芒澜,到底是詐尸還是另有隱情仰剿,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布痴晦,位于F島的核電站南吮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏阅酪。R本人自食惡果不足惜旨袒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一汁针、第九天 我趴在偏房一處隱蔽的房頂上張望术辐。 院中可真熱鬧,春花似錦施无、人聲如沸辉词。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瑞躺。三九已至,卻和暖如春兴想,著一層夾襖步出監(jiān)牢的瞬間幢哨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工嫂便, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捞镰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓毙替,卻偏偏與公主長得像岸售,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子厂画,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容