Skip to content

Commit

Permalink
feat: use jsonpath, countDocuments
Browse files Browse the repository at this point in the history
- Use jsonpath instead of searching reference field
> Fix the problem with `reference.reference` field cannot parse
> For better coding way
- Remove `checkReference` in apiService
> unused
- Use countDocuments instead of findOne for better performance
> findOne will return full document when exist
> we just need to check document is exist
> countDocuments may faster
  • Loading branch information
Chinlinlee committed Nov 4, 2022
1 parent 5133ae1 commit 7f88750
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 110 deletions.
122 changes: 24 additions & 98 deletions api/apiService.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,109 +51,35 @@ async function findResourceById(resource, id) {
}
}

async function checkReference(resourceData) {
let checkedReferenceList = [];
let resourceDeepKeys = getDeepKeys(resourceData);
let referenceKeys = resourceDeepKeys.filter(
v => v.endsWith(".reference")
);
for (let key of referenceKeys) {
let referenceValue = _.get(resourceData, key);
let referenceValueSplit = referenceValue.split('|')[0].split('/');
if (/^(http|https):\/\//g.test(referenceValue)) {
//do fetch to get response
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 1268 + 1231);
try {
let fetchRes = await fetch(referenceValue, {
headers: {
accept: "application/fhir+json"
} ,
signal: controller.signal
});
if (fetchRes.status == 200) {
let referenceJson = await fetchRes.json();
let fhir = new FHIR();
if (fhir.validate(referenceJson).valid) {
checkedReferenceList.push({
exist: true,
path: key,
value: referenceValue
});
} else {
checkedReferenceList.push({
exist: false,
path: key,
value: referenceValue
});
}
} else {
checkedReferenceList.push({
exist: false,
path: key,
value: referenceValue
});
}
} catch (e) {
checkedReferenceList.push({
exist: false,
path: key,
value: referenceValue
});
} finally {
clearTimeout(timeoutId);
}
} else if (referenceValueSplit.length >= 2) {
let resourceName = referenceValueSplit[referenceValueSplit.length - 2];
let resourceId = referenceValueSplit[referenceValueSplit.length - 1];
let doc = await findResourceById(resourceName, resourceId);
if (doc) {
checkedReferenceList.push({
exist: true,
path: key,
value: referenceValue
});
} else {
checkedReferenceList.push({
exist: false,
path: key,
value: referenceValue
});
}
} else if (/urn:oid:[0-2](\.[1-9]\d*)+/i.test(referenceValue) ||
/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(referenceValue)) {
//Only Bundle entry have OID or UUID reference?
let referenceTargetFullUrl = resourceDeepKeys.find(
v => _.get(resourceData, v) == referenceValue &&
v.endsWith("fullUrl")
);
if (referenceTargetFullUrl) {
checkedReferenceList.push({
exist: true,
path: key,
value: referenceValue
});
} else {
checkedReferenceList.push({
exist: false,
path: key,
value: referenceValue
});
}
/**
*
* @param {string} id The resource id
* @param {string} resourceType Resource type
* @returns status: 1 mean "exist", 2 mean "not exist", 0 mean "another error"
*/
async function isDocExist(id, resourceType) {
try {
let data = await mongodb[resourceType].countDocuments({id: id}).limit(1);
if (data > 0) {
return {
status: 1,
error: ""
};
}
}
if (checkedReferenceList.length > 0) {
return {
status : checkedReferenceList.every(v=> v.exist),
checkedReferenceList: checkedReferenceList
status: 2,
error: ""
};
} catch(e) {
console.error(e);
return {
status: 0,
error: e
};
}
return {
status: true,
checkedReferenceList: checkedReferenceList
};
}


function getNotExistReferenceList(checkReferenceRes) {
let notExistReferenceList = [];
for (let reference of checkReferenceRes.checkedReferenceList) {
Expand Down Expand Up @@ -187,7 +113,7 @@ module.exports = {
getDeepKeys: getDeepKeys,
isRealObject: isRealObject,
findResourceById: findResourceById,
checkReference: checkReference ,
isDocExist: isDocExist,
getNotExistReferenceList: getNotExistReferenceList,
renameCollectionFieldName: renameCollectionFieldName
};
19 changes: 7 additions & 12 deletions plugins/checkReference/middleware/checkReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const {
handleError
} = require('../../../models/FHIR/httpMessage');
const FHIR = require("fhir").Fhir;
const { getDeepKeys, findResourceById } = require("../../../api/apiService");
const { isDocExist } = require("../../../api/apiService");
const jp = require("jsonpath");

async function checkAbsoluteUrlRef(key, referenceValue, checkedReferenceList) {
//do fetch to get response
Expand Down Expand Up @@ -54,20 +55,17 @@ async function checkAbsoluteUrlRef(key, referenceValue, checkedReferenceList) {

async function checkReference(resourceData) {
let checkedReferenceList = [];
let resourceDeepKeys = getDeepKeys(resourceData);
let referenceKeys = resourceDeepKeys.filter(
v => v.endsWith(".reference")
);
for (let key of referenceKeys) {
let referenceKeysJp = jp.paths(resourceData, "$..reference").map( v=> v.join(".").substring(2));
for (let key of referenceKeysJp) {
let referenceValue = _.get(resourceData, key);
let referenceValueSplit = referenceValue.split('|')[0].split('/');
if (/^(http|https):\/\//g.test(referenceValue)) {
await checkAbsoluteUrlRef(key, referenceValue, checkedReferenceList);
} else if (referenceValueSplit.length >= 2) {
let resourceName = referenceValueSplit[referenceValueSplit.length - 2];
let resourceId = referenceValueSplit[referenceValueSplit.length - 1];
let doc = await findResourceById(resourceName, resourceId);
if (doc) {
let doc = await isDocExist(resourceId, resourceName);
if (doc.status === 1) {
checkedReferenceList.push({
exist: true,
path: key,
Expand All @@ -83,10 +81,7 @@ async function checkReference(resourceData) {
} else if (/urn:oid:[0-2](\.[1-9]\d*)+/i.test(referenceValue) ||
/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(referenceValue)) {
//Only Bundle entry have OID or UUID reference?
let referenceTargetFullUrl = resourceDeepKeys.find(
v => _.get(resourceData, v) == referenceValue &&
v.endsWith("fullUrl")
);
let referenceTargetFullUrl = jp.nodes(resourceData, "$..fullUrl").find( v=> v.value === referenceValue);
if (referenceTargetFullUrl) {
checkedReferenceList.push({
exist: true,
Expand Down

0 comments on commit 7f88750

Please sign in to comment.