Related
Given a bewildering fhir document like https://raw.githubusercontent.com/Notarise-gov-sg/api-notarise-healthcerts/master/test/fixtures/v2/pdt_art_with_nric_unwrapped.json
I need to update the part the JSON from { "id": "NRIC-FIN", "value": "S9098989Z" } to { "id": "NRIC-FIN", "value": "foobar" } and then emit the whole JSON again with that change.
I just about know how to access the value.
const fs = require("fs");
let rawdata = fs.readFileSync("pdt_art_with_nric_unwrapped.json");
let art = JSON.parse(rawdata);
let nric = art.fhirBundle.entry
.flatMap((entry) => entry.resource)
.find((entry) => entry.resourceType === "Patient")
.identifier.find((entry) => entry.id === "NRIC-FIN").value;
console.log(nric);
Though I am puzzled how to update this value since it's so difficult to access. Am I missing a trick? I don't want to use regex btw!
You seem to be very close - why not just set .value using the syntax you already have...?
const fs = require("fs");
let rawdata = fs.readFileSync("pdt_art_with_nric_unwrapped.json");
let art = JSON.parse(rawdata);
let nric = art.fhirBundle.entry
.flatMap((entry) => entry.resource)
.find((entry) => entry.resourceType === "Patient")
.identifier.find((entry) => entry.id === "NRIC-FIN").value = 'foobar';
console.dir(art.fhirBundle.entry)
... results in:
[
{
"fullUrl": "urn:uuid:ba7b7c8d-c509-4d9d-be4e-f99b6de29e23",
"resource": {
"resourceType": "Patient",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-nationality",
"extension": [
{
"url": "code",
"valueCodeableConcept": {
"text": "Patient Nationality",
"coding": [
{
"system": "urn:iso:std:iso:3166",
"code": "SG"
}
]
}
}
]
}
],
"identifier": [
{
"id": "PPN",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "PPN",
"display": "Passport Number"
}
]
},
"value": "E7831177G"
},
{
"id": "NRIC-FIN",
"value": "foobar"
}
],
"name": [
{
"text": "Tan Chen Chen"
}
],
"gender": "female",
"birthDate": "1990-01-15"
}
},
{
"fullUrl": "urn:uuid:7729970e-ab26-469f-b3e5-36a42ec24146",
"resource": {
"resourceType": "Observation",
"specimen": {
"type": "Specimen",
"reference": "urn:uuid:0275bfaf-48fb-44e0-80cd-9c504f80e6ae"
},
"performer": [
{
"type": "Practitioner",
"reference": "urn:uuid:3dbff0de-d4a4-4e1d-98bf-af7428b8a04b"
},
{
"id": "LHP",
"type": "Organization",
"reference": "urn:uuid:fa2328af-4882-4eaa-8c28-66dab46950f1"
}
],
"identifier": [
{
"id": "ACSN",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "ACSN",
"display": "Accession ID"
}
]
},
"value": "123456789"
}
],
"category": [
{
"coding": [
{
"system": "http://snomed.info/sct",
"code": "840539006",
"display": "COVID-19"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "97097-0",
"display": "SARS-CoV-2 (COVID-19) Ag [Presence] in Upper respiratory specimen by Rapid immunoassay"
}
]
},
"valueCodeableConcept": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "260385009",
"display": "Negative"
}
]
},
"effectiveDateTime": "2020-09-28T06:15:00Z",
"status": "final"
}
},
{
"fullUrl": "urn:uuid:0275bfaf-48fb-44e0-80cd-9c504f80e6ae",
"resource": {
"resourceType": "Specimen",
"subject": {
"type": "Device",
"reference": "urn:uuid:9103a5c8-5957-40f5-85a1-e6633e890777"
},
"type": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "697989009",
"display": "Anterior nares swab"
}
]
},
"collection": {
"collectedDateTime": "2020-09-27T06:15:00Z"
}
}
},
{
"fullUrl": "urn:uuid:3dbff0de-d4a4-4e1d-98bf-af7428b8a04b",
"resource": {
"resourceType": "Practitioner",
"name": [
{
"text": "Dr Michael Lim"
}
],
"qualification": [
{
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MCR",
"display": "Practitioner Medicare number"
}
]
},
"identifier": [
{
"id": "MCR",
"value": "123456"
}
],
"issuer": {
"type": "Organization",
"reference": "urn:uuid:bc7065ee-42aa-473a-a614-afd8a7b30b1e"
}
}
]
}
},
{
"fullUrl": "urn:uuid:bc7065ee-42aa-473a-a614-afd8a7b30b1e",
"resource": {
"resourceType": "Organization",
"name": "Ministry of Health (MOH)",
"type": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/organization-type",
"code": "govt",
"display": "Government"
}
]
}
],
"contact": [
{
"telecom": [
{
"system": "url",
"value": "https://www.moh.gov.sg"
},
{
"system": "phone",
"value": "+6563259220"
}
],
"address": {
"type": "physical",
"use": "work",
"text": "Ministry of Health, 16 College Road, College of Medicine Building, Singapore 169854"
}
}
]
}
},
{
"fullUrl": "urn:uuid:fa2328af-4882-4eaa-8c28-66dab46950f1",
"resource": {
"resourceType": "Organization",
"name": "MacRitchie Medical Clinic",
"type": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/organization-type",
"code": "prov",
"display": "Healthcare Provider"
}
],
"text": "Licensed Healthcare Provider"
}
],
"contact": [
{
"telecom": [
{
"system": "url",
"value": "https://www.macritchieclinic.com.sg"
},
{
"system": "phone",
"value": "+6561234567"
}
],
"address": {
"type": "physical",
"use": "work",
"text": "MacRitchie Hospital, Thomson Road, Singapore 123000"
}
}
]
}
},
{
"fullUrl": "urn:uuid:9103a5c8-5957-40f5-85a1-e6633e890777",
"resource": {
"resourceType": "Device",
"type": {
"coding": [
{
"system": "https://covid-19-diagnostics.jrc.ec.europa.eu/devices",
"code": "1232",
"display": "Abbott Rapid Diagnostics, Panbio COVID-19 Ag Rapid Test"
}
]
}
}
}
]
... clearly showing foobar set as you seem to desire. (Feel free to test with this Repl.it).
To "emit the full JSON" again you would just re-stringify it:
let fullJSON = JSON.stringify(art);
Instead of traversing the object manually you can use library like Jsonpath:
function replace() {
data = JSON.parse(data);
jsonpath.apply(data,
'$.fhirBundle.entry[?(#.resource.resourceType == "Patient")].resource.identifier[?(#.id == "NRIC-FIN")].value',
function(value) {
document.body.innerHTML += `value=${value}<br>`;
return 'foobar';
});
document.body.innerHTML += `updated JSON:<br> <pre>${JSON.stringify(data, undefined, 2)}</pre`;
}
let data =
`{
"id": "340139b0-8e92-4ed6-a589-d54730f52963",
"version": "pdt-healthcert-v2.0",
"type": "ART",
"validFrom": "2021-08-24T04:22:36.062Z",
"fhirVersion": "4.0.1",
"fhirBundle": {
"resourceType": "Bundle",
"type": "collection",
"entry": [
{
"fullUrl": "urn:uuid:ba7b7c8d-c509-4d9d-be4e-f99b6de29e23",
"resource": {
"resourceType": "Patient",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-nationality",
"extension": [
{
"url": "code",
"valueCodeableConcept": {
"text": "Patient Nationality",
"coding": [
{ "system": "urn:iso:std:iso:3166", "code": "SG" }
]
}
}
]
}
],
"identifier": [
{
"id": "PPN",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "PPN",
"display": "Passport Number"
}
]
},
"value": "E7831177G"
},
{ "id": "NRIC-FIN", "value": "S9098989Z" }
],
"name": [{ "text": "Tan Chen Chen" }],
"gender": "female",
"birthDate": "1990-01-15"
}
},
{
"fullUrl": "urn:uuid:0275bfaf-48fb-44e0-80cd-9c504f80e6ae",
"resource": {
"resourceType": "Specimen",
"subject": {
"type": "Device",
"reference": "urn:uuid:9103a5c8-5957-40f5-85a1-e6633e890777"
},
"type": {
"coding": [
{
"system": "http://snomed.info/sct",
"code": "697989009",
"display": "Anterior nares swab"
}
]
},
"collection": { "collectedDateTime": "2020-09-27T06:15:00Z" }
}
}
]
},
"issuers": [
{
"id": "did:ethr:0xE39479928Cc4EfFE50774488780B9f616bd4B830",
"revocation": { "type": "NONE" },
"name": "SAMPLE CLINIC",
"identityProof": {
"type": "DNS-DID",
"location": "donotverify.testing.verify.gov.sg",
"key": "did:ethr:0xE39479928Cc4EfFE50774488780B9f616bd4B830#controller"
}
}
],
"$template": {
"name": "HEALTH_CERT",
"type": "EMBEDDED_RENDERER",
"url": "https://healthcert.renderer.moh.gov.sg/"
}
}`
replace();
<script src="https://cdn.jsdelivr.net/npm/jsonpath#1.1.1/jsonpath.min.js"></script>
If you are flat out replacing values without any other logic, and in case if you decide to use RegEx, then you can use String.replace().
let data =
`{ "identifier": [
{
"id": "PPN",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "PPN",
"display": "Passport Number"
}
]
},
"value": "E7831177G"
},
{ "id": "NRIC-FIN", "value": "S9098989Z" }
],
"name": [{ "text": "Tan Chen Chen" }],
"gender": "female",
"birthDate": "1990-01-15"
}
}`
let targetId = 'NRIC-FIN';
let find = new RegExp(`(?<=${targetId}.*value":\\s*").*?(?=")`, 'ig');
data = data.replace(find, 'foobar');;
document.write(`<pre>${data}</pre>`);
Note: In the regular expression, I have used i flag for case insensitive search. Used g flag to replace all occurrences of the id. If the id is unique and there is going to be only one occurrence in entire .json file then don't use g flag.
I have a MongoDB collection "orders" with document similar to such:
{
"_id": ObjectId("xxxxx"),
"orderNo": 0,
"products": [
{ "product1": ["_Id": objectId("eeee"),"productName", "quantity", "price"] },
{ "product2": ["_Id": objectId("ffff"),"productName", "quantity", "price"] }
],
"deliveryAddress": "addsfdfghf"
}
{
"_id": ObjectId("yyyyy"),
"orderNo": 1,
"products": [
{ "product1": ["_Id": objectId("dddd"),"productName", "quantity", "price"] }
],
"deliveryAddress": "rwetrutytyi"
}
{
"_id": ObjectId("zzzz"),
"orderNo": 2,
"products": [
{ "product1": ["_Id": objectId("aaaa"), "productName", "quantity", "price"] },
{ "product2": ["_Id": objectId("bbbb"),"productName", "quantity", "price"] },
{ "product3": ["_Id": objectId("cccc"),"productName", "quantity", "price"] }
],
"deliveryAddress": "rwetrutytyi"
}
Now I want to write a query to get top selling products using "quantity" property of every products.
correct values of in above document look like:
{
"products": [{
"_id": {
"$oid": "612baf1b89c77b25c40aa3bc"
},
"productID": "NPZ6I",
"productName": "Cosentys 150ml",
"quantity": "1",
"expireDate": "04/20/2022",
"price": "22200"
}, {
"_id": {
"$oid": "612baf1b89c77b25c40aa3bb"
},
"productID": "NPZ3I",
"productName": "Asunra 400mg",
"quantity": "2",
"expireDate": "09/26/2021",
"price": "13200"
}],
"orderNo": 9,
"deliveryAddress": "Dhaka"
}
I want to return an object look like:
{
"_id": ObjectId("yyyyy"),
"productName": "String",
"productID": "String",
"totalSales" : "Number(sum of each products quantity)",
"totalEarning": "Number(sum of each product's price)"
}
I'm trying to sort a result like this one:
{
hits: {total: {value: 192, relation: "eq"}, max_score: 2.4924624,…}
hits: [
{
_id: "6501467",
_index: "nomenclator",
_score: 2.4924624,
atc: "M01AE01",
valorUnidadEnvase: "200",
},
{
_id: "6501467",
_index: "nomenclator",
_score: 2.4924624,
atc: "M01AE01",
valorUnidadEnvase: "20",
},
{
_id: "6501467",
_index: "nomenclator",
_score: 2.4924624,
atc: "M01AE01",
valorUnidadEnvase: "30",
}
]
...
This is just a fast example, the real one has to much fields.
I want to sort by "valorUnidadEnvase" in "asc", I'm trying it using a get request and the next query:
q: atc:M01*
size: 10
sort: [{"valorUnidadEnvase":{"order":"asc"}}]
But I'm not getting a sorted result
What am I ignoring or what do I need to sort this?
In your mapping, you need to define valorUnidadEnvase as Numeric field type
Adding a working example with index data, mapping, search query and search result
Index Mapping:
{
"mappings": {
"properties": {
"valorUnidadEnvase": {
"type": "integer"
}
}
}
}
Index Data:
{
"atc": "M01AE01",
"valorUnidadEnvase": "30"
}
{
"atc": "M01AE01",
"valorUnidadEnvase": "200"
}
{
"atc": "M01AE01",
"valorUnidadEnvase": "20"
}
Search Query:
{
"sort": [
{
"valorUnidadEnvase": {
"order": "asc"
}
}
]
}
Search Result:
"hits": [
{
"_index": "66985849",
"_type": "_doc",
"_id": "2",
"_score": null,
"_source": {
"atc": "M01AE01",
"valorUnidadEnvase": "20"
},
"sort": [
20
]
},
{
"_index": "66985849",
"_type": "_doc",
"_id": "3",
"_score": null,
"_source": {
"atc": "M01AE01",
"valorUnidadEnvase": "30"
},
"sort": [
30
]
},
{
"_index": "66985849",
"_type": "_doc",
"_id": "1",
"_score": null,
"_source": {
"atc": "M01AE01",
"valorUnidadEnvase": "200"
},
"sort": [
200
]
}
]
In my project I have user objects like this.
{
"_id": "1",
"username": "RAggro",
"name": "Vardan Tadevosyan"
},
{
"_id": "2",
"username": "XACHIK",
"name": "XACHIK"
},
{
"_id": "3",
"username": "vardar",
"name": "Vardan Gukoyan"
},
{
"_id": "4",
"username": "Gordey",
"name": "Gordey Gordeev"
},
{
"_id": "5",
"username": "id220107973",
"name": "Vardan Ayvazyan"
},
{
"_id": "6",
"username": "vvardanyan4",
"name": "Vardan Vardanyan"
},
{
"_id": "7",
"username": "svardan",
"name": "Vardan Sargsyan"
}
And I have list of _id-s, like [51,3,9,11,6, 2].
I whant to query users by 'name' and 'username', orderid like first comes users that contains in ids array then others
query: {
multi_match: {
query: "vardan",
fields: ["name", "username"],
operator: "or"
},
boosting: {
positive: {
term: {
_id: [51,3,9,11,6, 2]
}
},
positive_boost: 2.0
}
}
So the expected result is:
{
"_id": "3",
"username": "vardar",
"name": "Vardan Gukoyan"
},
{
"_id": "6",
"username": "vvardanyan4",
"name": "Vardan Vardanyan"
},
{
"_id": "1",
"username": "RAggro",
"name": "Vardan Tadevosyan"
},
{
"_id": "5",
"username": "id220107973",
"name": "Vardan Ayvazyan"
},
{
"_id": "7",
"username": "svardan",
"name": "Vardan Sargsyan"
}
But I'm fetching empty array,
Please, help how can I modify my query to reach expected ordered result.
You can do it easily using a bool/should clause that will boost the documents whose IDs are within the specified group:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "vardan",
"fields": [
"name",
"username"
],
"operator": "or"
}
}
],
"should": [
{
"ids": {
"values": ["51","3","9","11","6","2"]
}
}
]
}
}
}
It works using this query:
{
query:{
"bool": {
"must": [{
"multi_match": {
"query": "vardan",
"fields": [
"name",
"username"
],
"operator": "or"
}
}],
"should": [{
"terms": {
"_id": ["51","3","9","11","6","2"],
"boost": 100
}
}]
}
}
}
I have elastic Search data in following format:
{
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{ "name": "stellenbosch" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
},
{
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{ "name": "Rustenburg" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
},
{
"is_cricketer": 0,
"name": "deVilliers",
"cities": [
{ "name": "Cape town" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
}
I need to query elastic search to get all the profiles with is_cricketer = 1 and an OR query over the field for cities.name and name field. ie
( profile.is_cricketer == 1 && (profile.name == 'Abraham' || profile.cities[i].name == 'Nelspruit' ))
To get the profiles with OR query on the fields cities.name and name field for matching query string is as follows and it works a expected:
"should": [
{
"nested": {
"path": "cities",
"query": {
"multi_match": {
"query": "Nelspruit",
"fields": [
"cities.name"
]
}
}
}
},
{
"multi_match": {
"query": "Abraham",
"fields": [
"name"
]
}
}
]
And the Must query to get all the profiles with field is_cricketer = 1 is follows:
{
"must": {
"match": {
"is_cricketer": "1"
}
}
}
Above both queries working fine and i am trying to combine both query as follows:
{
"query": {
"bool": {
"must": {
"match": {
"is_cricketer": "1"
}
},
"should": [
{
"nested": {
"path": "cities",
"query": {
"multi_match": {
"query": "Nelspruit",
"fields": [
"cities.name"
]
}
}
}
},
{
"multi_match": {
"query": "Abraham",
"fields": [
"name"
]
}
}
]
}
}
}
which is not returning expected results, its returning all the profiles with is_cricketer = 1 without filtering for name and cities.name.
I also tried to include the should query inside must query as follows:
{
"query": {
"bool": {
"must": [{
"match": {
"is_cricketer": "1"
}
}, {
"should": [
{
"nested": {
"path": "cities",
"query": {
"multi_match": {
"query": "Nelspruit",
"fields": [
"cities.name"
]
}
}
}
},
{
"multi_match": {
"query": "Abraham",
"fields": [
"name"
]
}
}
]
}]
}
}
}
But i got following error for the above query:
"Error: [parsing_exception] [should] query malformed, no start_object
after query name, with { line=1 & col=64 }
at respond (/GitRepo/project/node_modules/elasticsearch/src/lib/transport.js:307:15)
at checkRespForFailure (/GitRepo/project/node_modules/elasticsearch/src/lib/transport.js:266:7)
at HttpConnector. (/GitRepo/project/node_modules/elasticsearch/src/lib/connectors/http.js:159:7)
at IncomingMessage.bound (/GitRepo/project/node_modules/elasticsearch/node_modules/lodash/dist/lodash.js:729:21)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1056:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)"
How to combine both the queries to get desired result. Any help will be appreciated.
if you want a should query inside a must you can use it in the following way
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
... your query here
}
]
}
}
]
}
}
}
This worked for me on ES 6.0.
Setup
PUT test1
{
"mappings": {
"type1": {
"properties": {
"cities": {
"type": "nested"
}
}
}
}
}
POST test1/type1
{
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{ "name": "stellenbosch" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
}
POST test1/type1
{
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{ "name": "Rustenburg" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
}
POST test1/type1
{
"is_cricketer": 0,
"name": "deVilliers",
"cities": [
{ "name": "Cape town" },
{ "name": "Nelspruit" },
{ "name": "East London" }
]
}
Query
GET test1/type1/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"is_cricketer": {
"value": 1
}
}
}
],
"should": [
{
"term": {
"name.keyword": {
"value": "Abraham"
}
}
},
{
"nested": {
"path": "cities",
"query": {
"term": {
"cities.name.keyword": {
"value": "Nelspruit"
}
}
}
}
}
]
}
}
}
Results - 2 hits
"hits": {
"total": 2,
"max_score": 2.2685113,
"hits": [
{
"_index": "test1",
"_type": "type1",
"_id": "zgcesWIBVwCaLf8KSuDi",
"_score": 2.2685113,
"_source": {
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{
"name": "stellenbosch"
},
{
"name": "Nelspruit"
},
{
"name": "East London"
}
]
}
},
{
"_index": "test1",
"_type": "type1",
"_id": "eAQesWIBbxh35CpKckEH",
"_score": 2.2685113,
"_source": {
"is_cricketer": 1,
"name": "Abraham",
"cities": [
{
"name": "Rustenburg"
},
{
"name": "Nelspruit"
},
{
"name": "East London"
}
]
}
}
]
}