一、思路
    首先,记事本json格式的文件,里面的单条数据有$oid, 这个$oid是mongodb数据库特有的索引数据。image.png
    1、我们需要先把json格式数据(这个JSON数据不是JavaScript可以处理)需要导入到mongodb数据库(可以使用mongodb可视化工具compass);

    2、将数据导入完毕后,筛选后导出成 JavaScript可以处理的JSON数据,通过node 插入到数据库;
    3、使用mssql 插件连接数据库, 之前按照往上文档一直连接不上,因为少了红框的部分
    image.png

    1. var dbConfig = {
    2. user: 'sa',
    3. password: 'PPKao2106',
    4. server: '192.168.1.220',
    5. database: 'lltk',
    6. port: 1433,
    7. pool: {
    8. max: 10,
    9. min: 0,
    10. idleTimeoutMillis: 30000
    11. },
    12. options: {
    13. encrypt: false, // for azure
    14. trustServerCertificate: false // change to true for local dev / self-signed certs
    15. }
    16. };

    二、碰到的问题
    1、 “_id” : { “$oid” : “5b2fbe24e0ab55c88fa1a4ad” }
    解答:这个是mongodb数据 导出的数据就是这样的,自带了id,导出的时候可以筛选不用带这个id;

    2、node 如何读取Json文件,使用 fs.readFileSync(‘./data/gongwuyuan.json’,’utf8’ ), utf8是告知应该用何种数据格式进行读取。 默认是buffer 数据格式;导出的数据是有效的json字符串,需要使用JSON.parse转换成数组JSON文件进行处理。
    image.png

    3、node读取较大文件报错如何处理?
    node 读取大文件会报错,因为fs.readFileSync读取文件是将文件一次性读取到本地内存。而如果读取文件超过400M左右就会报错,因为占用了大量内存,效率低。我们就要用流来读取。流是将数据分割段,一段一段的读取,可以控制速率,效率很高,不会占用大量内存。gulp的task任务,文件压缩,和http中的请求和响应功能的实现都是基于流来实现的
    流的用法

    1. 1. node中读是将内容读取到内存中,而内存就是Buffer 对象
    2. 2. 流都是基于原生的fs 操作文件的方法来实现的,通过fs 创建流。所有的Stream 对象都是EventEmitter 的实例。常用的事件有:
    3. 1. open - 打开文件
    4. 2. data - 当有数据可读的时候触发
    5. 3. error - 在读取和写如过程中发生错误时触发。
    6. 4. close - 关闭文件
    7. 5. end - 没有更多的数据可读时触发
    1. let fs = require('fs');
    2. let rs = fs.createReadStream('./1.text', {
    3. highWaterMark:3, // 文件一次读多少个字节,默认 64*1024
    4. flags: 'r', // 默认 'r'
    5. autoClose: true, // 默认读取完毕后自动关闭
    6. start: 0, //读取文件开始位置
    7. end: 3, // 流是闭合区间, 包含start 也含 end
    8. encoding: 'utf8' //默认null
    9. })
    10. //监听文件open方法
    11. rs.on('open', () => {
    12. console.log('文件打开')
    13. })
    14. // 只要文件没读取完 这个方法会一直触发, 直到读取完毕
    15. rs.on('data', (data) => {
    16. console.log(data); //
    17. })
    18. rs.pause() // 暂定读取, 会暂停data事件的触发,将流动模式转为非流动模式
    19. rs.resume() // 恢复data 事件,继续读取,变为流动模式
    20. rs.on('err', () => {
    21. console.log("发生错误")
    22. })
    23. rs.on('end', () => {
    24. console.log("读取完毕")
    25. })
    26. rs.on("close",()=>{ //最后文件关闭触发
    27. console.log("关闭")
    28. });
    1. 但是 问题又出现了, 流的操作是每次都读取固定的字节数量,会导致每次读取的可能不是完整的字符串,所以就不能连接字符串的操作, 如下图所示;<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/95588/1660098625779-98ac48e0-a397-4854-8282-0bef322ce198.png#clientId=u9261e3ce-df42-4&from=paste&height=190&id=u8f5f228b&originHeight=237&originWidth=483&originalType=binary&ratio=1&rotation=0&showTitle=false&size=16498&status=done&style=none&taskId=ua1b2f568-334d-4c59-8002-55488baa5fc&title=&width=386.4)<br />我们可以使用一个叫JSONStream 的插件进行处理,这个插件是基于流的,每次data 返回的是一个对象,正好满足我们的需求,每次返回一个对象,我们就处理一下,插入到数据库!
    1. function ShiTiData() {
    2. console.log(KaoShiShiTi.length) //3214 先500开始(采集完了)
    3. sql.connect(dbConfig).then(function async() {
    4. // for(let i = 0; i < KaoShiShiTi.length; i++ ) {
    5. // for(let i = 3000; i < 3215; i++ ) {
    6. // const { stData } = GongWuYuan[i];
    7. const readable = fs.createReadStream('./data/medicine.json', {
    8. encoding: 'utf8',
    9. highWaterMark: 10
    10. })
    11. const parser = JSONStream.parse('.');
    12. readable.pipe(parser);
    13. parser.on('data', (data) => {
    14. const { stData } = data;
    15. // console.log(stData, 'stData', stData.length)
    16. if(stData && stData.length > 0) {
    17. console.log(stData, 'dataaaaaaaaaaaaaaaaaaaaaa', stData.length)
    18. for(let stDataIndex = 0; stDataIndex < stData.length; stDataIndex ++) {
    19. if(stData[stDataIndex].examCardStatusList && stData[stDataIndex].examCardStatusList.examDtoList && stData[stDataIndex].examCardStatusList.examDtoList.length > 0) {
    20. let topicList = stData[stDataIndex].examCardStatusList.examDtoList;
    21. for(let topicIndex = 0; topicIndex < topicList.length; topicIndex++) {
    22. let { examId, answer, analysis, content, examType, examTypeName, selectNum, optionList, videoAnalysis, videoAnalysisId, videoCoverUrl, md5, tikuId } = topicList[topicIndex];
    23. if(optionList && optionList.length > 0) {
    24. optionList = handdleOptionList(optionList);
    25. }
    26. new sql.Request().query(
    27. `insert into ShiTi (examId,answer,analysis, content, examType, examTypeName, selectNum, optionList, videoAnalysis, videoAnalysisId, videoCoverUrl, md5, tikuId ) values
    28. ('${examId}','${answer}','${analysis}', '${content}', '${examType}', '${examTypeName}', '${selectNum}','${optionList}','${videoAnalysis}', '${videoAnalysisId}', '${videoCoverUrl}', '${md5}', '${tikuId}')`,
    29. );
    30. }
    31. }
    32. if(stData[stDataIndex].examCardStatusList && !stData[stDataIndex].examCardStatusList.examDtoList && stData[stDataIndex].examCardStatusList.length > 0){
    33. let topicList = stData[stDataIndex].examCardStatusList;
    34. for(let topicIndex = 0; topicIndex < topicList.length; topicIndex++) {
    35. let { examId, answer, analysis, content, examType, examTypeName, selectNum, optionList, videoAnalysis, videoAnalysisId, videoCoverUrl, md5, tikuId } = topicList[topicIndex];
    36. console.log(`examId=${examId};answer=${answer}`)
    37. if(optionList && optionList.length > 0) {
    38. optionList = handdleOptionList(optionList);
    39. }
    40. new sql.Request().query(
    41. `insert into ShiTi (examId,answer,analysis, content, examType, examTypeName, selectNum, optionList, videoAnalysis, videoAnalysisId, videoCoverUrl, md5, tikuId ) values
    42. ('${examId}','${answer}','${analysis}', '${content}', '${examType}', '${examTypeName}', '${selectNum}','${optionList}','${videoAnalysis}', '${videoAnalysisId}', '${videoCoverUrl}', '${md5}', '${tikuId}')`,
    43. );
    44. }
    45. }
    46. }
    47. }
    48. });
    49. }).catch(function (err) {
    50. console.log(err);
    51. });
    52. }