1
0

knowledgeBase.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. //© 2019 Dublin City University, Trinity College Dublin. All rights reserved. This material may not be reproduced, displayed, modified or distributed without the express prior written permission of the copyright holder.
  2. var path = require('path');
  3. var fs = require('fs');
  4. var cache = require('memory-cache');
  5. const knowledgeBaseFile = __dirname + '/output';
  6. const statusFile = __dirname + '/status/statusStore.json';
  7. const axios = require('axios');
  8. const queryString = require('query-string');
  9. const knowledgeBaseModel = require(__dirname + '/model/knowledgeBaseModel.js');
  10. var Promise = require('promise');
  11. const headers = { 'Accept': 'application/sparql-results+json', 'Content-Type': 'application/x-www-form-urlencoded' };
  12. axios.defaults.timeout = 5000;
  13. const UndefinedClassesAndPropertiesMetricQuery = require(__dirname + '/sparql/UndefinedClassesAndPropertiesMetric');
  14. const HumanReadableLabellingMetricQuery = require(__dirname + '/sparql/HumanReadableLabellingMetric');
  15. const CompatibleDatatypeQuery = require(__dirname + '/sparql/CompatibleDatatype');
  16. const EntitiesAsMembersOfDisjointClassesMetricQuery = require(__dirname + '/sparql/EntitiesAsMembersOfDisjointClassesMetric');
  17. const MisplacedClassesOrPropertiesMetricQuery = require(__dirname + '/sparql/MisplacedClassesOrPropertiesMetric');
  18. const MisusedOwlDatatypeOrObjectPropertiesMetricQuery = require(__dirname + '/sparql/MisusedOwlDatatypeOrObjectPropertiesMetric');
  19. const UsageOfIncorrectDomainOrRangeDatatypesMetricQuery = require(__dirname + '/sparql/UsageOfIncorrectDomainOrRangeDatatypesMetric');
  20. const ExtensionalConcisenessMetricQuery_FetchProblem = require(__dirname + '/sparql/ExtensionalConcisenessMetric_FetchProblem');
  21. const ExtensionalConcisenessMetricQuery_FetchAllTriples = require(__dirname + '/sparql/ExtensionalConcisenessMetric_FetchAllTriples');
  22. const ExtensionalConcisenessMetricQuery_FindRelated = require(__dirname + '/sparql/ExtensionalConcisenessMetric_FindRelated');
  23. class knowledgeBases {
  24. getKnowledgeBase(req, res) {
  25. const knowledgeBaseID = parseInt(req.query.knowledgeBaseID, 10);
  26. let knowledgeBase=cache.get(knowledgeBaseID);
  27. let kbStatus=cache.get(knowledgeBaseID+"_STATUS")
  28. if(knowledgeBase===null)
  29. {
  30. return res.status(404).send({
  31. status: 'false',
  32. message: 'Knowledge Base not Created',
  33. });
  34. }
  35. else
  36. {
  37. if(kbStatus==="COMPLETED")
  38. {
  39. return res.status(200).send(
  40. {knowledgeBase}
  41. );
  42. }
  43. else
  44. {
  45. return res.status(404).send({
  46. status: 'false',
  47. message: 'Knowledge Base not Created',
  48. });
  49. }
  50. }
  51. }
  52. getKnowledgeBaseStatus(req, res) {
  53. const knowledgeBaseID = parseInt(req.query.knowledgeBaseID, 10);
  54. let knowledgeBase=cache.get(knowledgeBaseID);
  55. let kbStatus=cache.get(knowledgeBaseID+"_STATUS")
  56. if(knowledgeBase===null)
  57. {
  58. console.log(knowledgeBaseID + ": Is Null");
  59. return res.status(404).send({
  60. status: 'false',
  61. message: 'Knowledge Base Not Found'
  62. });
  63. }
  64. else
  65. {
  66. console.log(knowledgeBaseID + ":"+ knowledgeBase.length);
  67. if(kbStatus==="INPROGRESS")
  68. {
  69. let percentage = cache.get(knowledgeBaseID+"_PERCENTAGE");
  70. console.log("Percentage :"+ percentage );
  71. return res.status(200).send({
  72. knowledgeBaseID: knowledgeBaseID,
  73. status: 'INPROGRESS',
  74. percentage: percentage
  75. });
  76. }
  77. else if (kbStatus==="COMPLETED")
  78. {
  79. return res.status(200).send({
  80. knowledgeBaseID: knowledgeBaseID,
  81. status : 'COMPLETED'
  82. });
  83. }
  84. else
  85. {
  86. return res.status(404).send({
  87. status: 'false',
  88. message: 'Knowledge Base Not Found'
  89. });
  90. }
  91. }
  92. }
  93. generateKnowledgeBase(req, res) {
  94. const metrics = req.body.metrics;
  95. //const metrics = JSON.parse(req.body.metrics);
  96. const qualityGraph = req.body.qualityGraph;
  97. const dataGraph = req.body.dataGraph;
  98. const tripleStoreEndPoint = req.body.tripleStoreEndPoint;
  99. const isSparqlEndPoint = req.body.isSparqlEndPoint;
  100. const lastAssessmentDate = req.body.lastAssessmentDate;
  101. const knowledgeBaseMapping = req.body.knowledgeBaseMapping;
  102. let queryResults = [];
  103. let datasetSource = 'GRAPH';
  104. if(isSparqlEndPoint==='true')
  105. {
  106. //console.log("IS SPARQL ENDPOINT");
  107. datasetSource='SERVICE';
  108. }
  109. let knowledgeBaseID = Math.floor(Date.now());
  110. console.log(knowledgeBaseID );
  111. cache.put(knowledgeBaseID,queryResults);
  112. cache.put(knowledgeBaseID+"_STATUS","INPROGRESS",42000000);
  113. cache.put(knowledgeBaseID+"_PERCENTAGE",0,42000000);
  114. const knowledgeBaseNew = {
  115. knowledgeBaseID: knowledgeBaseID
  116. };
  117. function setImmediatePromise() {
  118. return new Promise((resolve) => {
  119. setImmediate(() => resolve());
  120. });
  121. }
  122. console.log("Metrics : "+metrics.length);
  123. var buildResultArray = function (query) {
  124. return new Promise(function (resolve, reject) {
  125. //console.log("MAKING SPARQL CALL" );
  126. axios.post(tripleStoreEndPoint, queryString.stringify({ query: query }), headers)
  127. .then(response => {
  128. //console.log("SPARQL CALL MADE" );
  129. if (response) {
  130. //console.log("RESPONSE RECEIDED" );
  131. if (response.status === 200) {
  132. //console.log("200 CODE" );
  133. console.log("buildResultArray : "+response.data.results.bindings.length);
  134. response.data.results.bindings.forEach(function (binding) {
  135. let ProblematicThing = "";
  136. let Subject = "";
  137. let Predicate = "";
  138. let Object = "";
  139. let FailedMertic = "";
  140. let Exception = "";
  141. if (binding.Subject !== undefined) {
  142. Subject = "<"+binding.Subject.value+">";
  143. }
  144. if (binding.Predicate !== undefined) {
  145. Predicate = "<"+binding.Predicate.value+">";
  146. }
  147. if (binding.Object !== undefined) {
  148. if(binding.Object.type==="uri")
  149. {
  150. Object +="<"+binding.Object.value+">";
  151. }
  152. else
  153. {
  154. if(binding.Object["xml:lang"]!==undefined)
  155. {
  156. Object +="\"\"\""+binding.Object.value+"\"\"\"@" +binding.Object["xml:lang"];
  157. }
  158. else if(binding.Object["datatype"]!==undefined)
  159. {
  160. let value = binding.Object.value.replace(/(\"|\')/g, '\\$1');
  161. Object +="\"\"\""+value+"\"\"\""+"^^<" +binding.Object["datatype"]+">" ;
  162. }
  163. else{
  164. Object +="\"\"\""+binding.Object.value+"\"\"\"";
  165. }
  166. }
  167. }
  168. if (binding.FailedMertic !== undefined) {
  169. //FailedMertic = binding.FailedMertic.value;
  170. FailedMertic = binding.FailedMertic.value.split("#")[1];
  171. }
  172. if (binding.Exception !== undefined) {
  173. //Exception = binding.Exception.value;
  174. Exception = binding.Exception.value.split("#")[1];
  175. }
  176. ProblematicThing = knowledgeBaseMapping[FailedMertic][Exception];
  177. let temp = {
  178. "ProblematicThing": ProblematicThing,
  179. "Subject": Subject,
  180. "Predicate": Predicate,
  181. "Object": Object,
  182. "FailedMertic": FailedMertic,
  183. "Exception": Exception
  184. }
  185. queryResults.push(temp);
  186. });
  187. }
  188. else
  189. {
  190. //console.log("NOT 200 CODE" );
  191. reject(error);
  192. }
  193. }
  194. //console.log("RESOLVING" );
  195. resolve();
  196. })
  197. .catch(error => {
  198. //console.log("REJECTING" );
  199. reject(error);
  200. });
  201. });
  202. }
  203. var buildextensionalConcisenessMetricProblems = function (query) {
  204. return new Promise(function (resolve, reject) {
  205. let queryResultsTemp=[];
  206. axios.post(tripleStoreEndPoint, queryString.stringify({ query: query }), headers)
  207. .then(response => {
  208. if (response) {
  209. if (response.status === 200) {
  210. console.log("buildextensionalConcisenessMetricProblems : "+response.data.results.bindings.length);
  211. response.data.results.bindings.forEach(function (binding) {
  212. let ProblematicThing = "";
  213. let Subject = "";
  214. let Predicate = "";
  215. let Object = "";
  216. let FailedMertic = "";
  217. let Exception = "";
  218. if (binding.Subject !== undefined) {
  219. Subject = "<"+binding.Subject.value+">";
  220. }
  221. if (binding.Predicate !== undefined) {
  222. Predicate = "<"+binding.Predicate.value+">";
  223. }
  224. if (binding.FailedMertic !== undefined) {
  225. //FailedMertic = binding.FailedMertic.value;
  226. //FailedMertic = binding.FailedMertic.value.split("#")[1];
  227. FailedMertic = "ExtensionalConcisenessMetric";
  228. }
  229. if (binding.Exception !== undefined) {
  230. //Exception = binding.Exception.value;
  231. Exception = binding.Exception.value.split("#")[1];
  232. }
  233. //ProblematicThing = knowledgeBaseMapping[FailedMertic][Exception];
  234. ProblematicThing = knowledgeBaseMapping["ExtensionalConcisenessMetric"]["ResourceReplica"];
  235. let temp = {
  236. "ProblematicThing": ProblematicThing,
  237. "Subject": Subject,
  238. "Predicate": Predicate,
  239. "Object": Object,
  240. "FailedMertic": FailedMertic,
  241. "Exception": Exception
  242. }
  243. queryResultsTemp.push(temp);
  244. });
  245. }
  246. }
  247. resolve(queryResultsTemp);
  248. })
  249. .catch(error => {
  250. //reject(queryResultsTemp);
  251. resolve(queryResultsTemp);
  252. });
  253. });
  254. }
  255. var buildextensionalConcisenessAllTripleQuery = function (query) {
  256. return new Promise(function (resolve, reject) {
  257. let triples="";
  258. axios.post(tripleStoreEndPoint, queryString.stringify({ query: query }), headers)
  259. .then(response => {
  260. if (response) {
  261. if (response.status === 200) {
  262. console.log("buildextensionalConcisenessAllTripleQuery : "+response.data.results.bindings.length);
  263. let length=response.data.results.bindings.length;
  264. response.data.results.bindings.forEach(function (binding,index)
  265. {
  266. if(index===0)
  267. {
  268. triples="?Resource ";
  269. }
  270. triples +="<"+binding.Predicate.value+"> ";
  271. if(binding.Object.type==="uri")
  272. {
  273. triples +="<"+binding.Object.value+"> ";
  274. }
  275. else
  276. {
  277. if(binding.Object["xml:lang"]!==undefined)
  278. {
  279. triples +="\"\"\""+binding.Object.value+"\"\"\"@" +binding.Object["xml:lang"]+" " ;
  280. }
  281. else if(binding.Object["datatype"]!==undefined)
  282. {
  283. let value = binding.Object.value.replace(/(\"|\')/g, '\\$1');
  284. //triples += "\"s\" ";
  285. triples +="\"\"\""+value+"\"\"\""+"^^<" +binding.Object["datatype"]+"> " ;
  286. }
  287. else{
  288. triples +="\"\"\""+binding.Object.value+"\"\"\" ";
  289. }
  290. }
  291. if(!(index===length-1))
  292. {
  293. triples += "; ";
  294. }
  295. });
  296. }
  297. }
  298. resolve(triples);
  299. })
  300. .catch(error => {
  301. //reject(triples);
  302. resolve(triples);
  303. });
  304. });
  305. }
  306. var buildextensionalConcisenessResultArray = function (query) {
  307. return new Promise(function (resolve, reject) {
  308. let related=[];
  309. axios.post(tripleStoreEndPoint, queryString.stringify({ query: query }), headers)
  310. .then(response => {
  311. if (response) {
  312. if (response.status === 200) {
  313. console.log("buildextensionalConcisenessResultArray : "+response.data.results.bindings.length);
  314. let length=response.data.results.bindings.length;
  315. response.data.results.bindings.forEach(function (binding,index)
  316. {
  317. related.push(binding.Resource.value);
  318. });
  319. }
  320. }
  321. resolve(related);
  322. })
  323. .catch(error => {
  324. //reject(related);
  325. resolve(related);
  326. });
  327. });
  328. }
  329. var triggerActivity = async function () {
  330. for (const metric of metrics) {
  331. let query = "";
  332. switch (metric.metric) {
  333. case 'UndefinedClassesAndPropertiesMetric':
  334. console.log("UndefinedClassesAndPropertiesMetric:"+datasetSource);
  335. query = UndefinedClassesAndPropertiesMetricQuery.UndefinedClassesAndPropertiesMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  336. await buildResultArray(query);
  337. break;
  338. case 'HumanReadableLabellingMetric':
  339. console.log("HumanReadableLabellingMetric:"+datasetSource);
  340. query = HumanReadableLabellingMetricQuery.HumanReadableLabellingMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  341. await buildResultArray(query);
  342. break;
  343. case 'CompatibleDatatype':
  344. console.log("CompatibleDatatype:"+datasetSource);
  345. query = CompatibleDatatypeQuery.CompatibleDatatype(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  346. await buildResultArray(query);
  347. break;
  348. case 'EntitiesAsMembersOfDisjointClassesMetric':
  349. console.log("EntitiesAsMembersOfDisjointClassesMetric:"+datasetSource);
  350. query = EntitiesAsMembersOfDisjointClassesMetricQuery.EntitiesAsMembersOfDisjointClassesMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  351. await buildResultArray(query);
  352. break;
  353. case 'MisplacedClassesOrPropertiesMetric':
  354. console.log("MisplacedClassesOrPropertiesMetric:"+datasetSource);
  355. query = MisplacedClassesOrPropertiesMetricQuery.MisplacedClassesOrPropertiesMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  356. await buildResultArray(query);
  357. break;
  358. case 'MisusedOwlDatatypeOrObjectPropertiesMetric':
  359. console.log("MisusedOwlDatatypeOrObjectPropertiesMetric:"+datasetSource);
  360. query = MisusedOwlDatatypeOrObjectPropertiesMetricQuery.MisusedOwlDatatypeOrObjectPropertiesMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  361. await buildResultArray(query);
  362. break;
  363. case 'UsageOfIncorrectDomainOrRangeDatatypesMetric':
  364. console.log("UsageOfIncorrectDomainOrRangeDatatypesMetric:"+datasetSource);
  365. query = UsageOfIncorrectDomainOrRangeDatatypesMetricQuery.UsageOfIncorrectDomainOrRangeDatatypesMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  366. await buildResultArray(query);
  367. break;
  368. case 'ExtensionalConcisenessMetric':
  369. console.log("ExtensionalConcisenessMetric:"+datasetSource);
  370. query = ExtensionalConcisenessMetricQuery_FetchProblem.ExtensionalConcisenessMetric(qualityGraph, dataGraph, metric.observationURI,datasetSource);
  371. let queryResultsTemp = await buildextensionalConcisenessMetricProblems(query);
  372. //console.log(queryResultsTemp);
  373. let alreadyFoundList = [];
  374. let alreadFoundBoolean = false;
  375. for(const problem of queryResultsTemp)
  376. {
  377. alreadFoundBoolean=false;
  378. //console.log("PROBLEM : "+problem.Subject);
  379. let subject = problem.Subject;
  380. for(const inList of alreadyFoundList)
  381. {
  382. if(inList===subject)
  383. {
  384. alreadFoundBoolean=true;
  385. }
  386. }
  387. if(!alreadFoundBoolean)
  388. {
  389. query = ExtensionalConcisenessMetricQuery_FetchAllTriples.ExtensionalConcisenessMetric(qualityGraph, dataGraph, subject,datasetSource);
  390. let triples = await buildextensionalConcisenessAllTripleQuery(query);
  391. //console.log(triples);
  392. let relatedResourcesQuery=ExtensionalConcisenessMetricQuery_FindRelated.ExtensionalConcisenessMetric(triples, dataGraph, subject,datasetSource);
  393. let relatedResources=await buildextensionalConcisenessResultArray(relatedResourcesQuery);
  394. //console.log(relatedResources);
  395. for(const related of relatedResources)
  396. {
  397. let tempProblem = null;
  398. tempProblem=JSON.parse(JSON.stringify(problem));
  399. tempProblem["Object"]="<"+related+">"
  400. queryResults.push(tempProblem);
  401. alreadyFoundList.push("<"+related+">");
  402. }
  403. }
  404. }
  405. break;
  406. default:
  407. console.log("default:"+datasetSource);
  408. query = "";
  409. break;
  410. }
  411. }
  412. }
  413. triggerActivity().then(async function () {
  414. //console.log("AFTER TRIGGER ACTIVITY");
  415. console.log("ARRAY COUNT : "+queryResults.length);
  416. //Loop through each array object
  417. var start = Date.now();
  418. for (const [outerIndex, outerResult] of queryResults.entries()) {
  419. //let resourceRelatedExceptions = [];
  420. //let problematicThingRelatedExceptions = [];
  421. let SubjectRelatedException = [];
  422. let PredicateRelatedException = [];
  423. let ObjectRelatedException = [];
  424. let tempArray = [];
  425. let tempSubjectRelatedException = [];
  426. let tempPredicateRelatedException = [];
  427. let tempObjectRelatedException = [];
  428. //console.log(outerIndex);
  429. //console.log((outerIndex+1)/queryResults.length);
  430. cache.del(knowledgeBaseID+"_PERCENTAGE");
  431. cache.put(knowledgeBaseID+"_PERCENTAGE",(outerIndex+1)/queryResults.length,42000000);
  432. //console.log(outerIndex);
  433. //Add Await call to setImmediate to prevent thread blocking
  434. await setImmediatePromise()
  435. //Find Resource related Exceptions
  436. tempArray = [];
  437. for (const [innerIndex, innerResult] of queryResults.entries()) {
  438. //if (outerResult.Subject === innerResult.Subject & outerResult.Exception !== innerResult.Exception) {
  439. if (outerResult.Subject === innerResult.Subject) {
  440. tempArray.push(innerResult.Exception);
  441. }
  442. }
  443. //resourceRelatedExceptions = [...new Set(tempArray.map((exception) => (exception)))];
  444. //queryResults[outerIndex].resourceRelatedExceptions = [...resourceRelatedExceptions];
  445. SubjectRelatedException = [...new Set(tempArray.map((exception) => (exception)))];
  446. queryResults[outerIndex].SubjectRelatedException = [...SubjectRelatedException];
  447. //Find Problematic Thing Related Exceptions
  448. //tempArray = [];
  449. tempSubjectRelatedException = [];
  450. tempPredicateRelatedException = [];
  451. tempObjectRelatedException = [];
  452. for(const outerResultProblematicThing of outerResult.ProblematicThing)
  453. {
  454. for (const [innerIndex, innerResult] of queryResults.entries()) {
  455. //if (outerResult[outerResultProblematicThing] === innerResult[outerResultProblematicThing] & outerResult.Exception !== innerResult.Exception) {
  456. if (outerResult[outerResultProblematicThing] === innerResult[outerResultProblematicThing]) {
  457. //tempArray.push(innerResult.Exception);
  458. //SubjectRelatedExceptions is same as ResourceRelatedException
  459. //if(outerResultProblematicThing==="Subject")
  460. //{
  461. //tempSubjectRelatedException.push(innerResult.Exception);
  462. //}
  463. if(outerResultProblematicThing==="Predicate")
  464. {
  465. tempPredicateRelatedException.push(innerResult.Exception);
  466. }
  467. if(outerResultProblematicThing==="Object")
  468. {
  469. tempObjectRelatedException.push(innerResult.Exception);
  470. }
  471. }
  472. }
  473. }
  474. //problematicThingRelatedExceptions = [...new Set(tempArray.map((exception) => (exception)))];
  475. //queryResults[outerIndex].problematicThingRelatedExceptions = [...problematicThingRelatedExceptions];
  476. //subjectRelatedException = [...new Set(tempSubjectRelatedException.map((exception) => (exception)))];
  477. //queryResults[outerIndex].subjectRelatedException = [...subjectRelatedException];
  478. PredicateRelatedException = [...new Set(tempPredicateRelatedException.map((exception) => (exception)))];
  479. queryResults[outerIndex].PredicateRelatedException = [...PredicateRelatedException];
  480. ObjectRelatedException = [...new Set(tempObjectRelatedException.map((exception) => (exception)))];
  481. queryResults[outerIndex].ObjectRelatedException = [...ObjectRelatedException];
  482. //console.log(queryResults);
  483. /*
  484. //For Future Purpose
  485. queryResults[outerIndex].RootProblematicThing = "";
  486. queryResults[outerIndex].RootCauseException = "";
  487. //STORING TO DB
  488. let knowledgeBaseDocumentToSave = new knowledgeBaseModel(queryResults[outerIndex]);
  489. let ObjectID = await knowledgeBaseDocumentToSave.save();
  490. //console.log(ObjectID['_id']);
  491. queryResults[outerIndex].ObjectID = ObjectID['_id'];
  492. */
  493. }
  494. var end = Date.now();
  495. var elapsed = end - start;
  496. function millisToMinutesAndSeconds(millis) {
  497. var minutes = Math.floor(millis / 60000);
  498. var seconds = ((millis % 60000) / 1000).toFixed(0);
  499. return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
  500. }
  501. console.log(millisToMinutesAndSeconds(elapsed));
  502. //Update Status as Completed
  503. //console.log(queryResults)
  504. console.log("UPDATING CACHE");
  505. cache.del(knowledgeBaseID);
  506. cache.put(knowledgeBaseID,queryResults,42000000);
  507. cache.del(knowledgeBaseID+"_STATUS");
  508. cache.put(knowledgeBaseID+"_STATUS","COMPLETED",42000000);
  509. console.log("Generated");
  510. }
  511. ).catch(function(error){
  512. console.log("ERROR_" + error);
  513. cache.del(knowledgeBaseID);
  514. });
  515. return res.status(201).send(knowledgeBaseNew);
  516. }
  517. }
  518. const knowledgeBase = new knowledgeBases();
  519. export default knowledgeBase;