Skip to main content

Search Data

Once an entity (such as a patient or a medical record) is created, you can always retrieve it using its ID. However, in most cases, you might not have the ID of the entity you need. Therefore, the Cardinal SDK allows you to search data by their content using filters.

The following examples provide insights into how to search data using the filter mechanism. For a more comprehensive understanding, check this how to.

In the first code snippet, all patients whose name matches the query string provided by the user and who are shared with the current user will be returned:

print("Enter a name: ")
val nameToSearch = readln()
val patientIterator = sdk.patient.filterPatientsBy(
PatientFilters.byNameForSelf(nameToSearch)
)

PatientFilters.byNameForSelf defines the options used to retrieve the patients, while the filterPatientsBy method is responsible for actually getting them. This method returns an iterator with two methods: hasNext(), which returns true if there is at least one more entity available, and next(X), which retrieves up to the next X available entities, with a minimum of 1.

Here’s an example of how to use this iterator:

var patient: Patient? = null
while (patientIterator.hasNext() && patient == null) {
val p = patientIterator.next(1).first()
prettyPrint(p)
print("Use this patient? [y/N]: ")
val use = readln().trim().lowercase() == "y"
if (use) {
patient = p
}
}

if (patient == null) {
println("No matching patient found")
return
}

The same logic can be applied to medical data, where you can leverage the secret link between a patient and another entity:

val contactIterator = sdk.contact.filterContactsBy(
ContactFilters.byPatientsForSelf(listOf(patient))
)

if (!contactIterator.hasNext()) {
println("No matching contacts found")
}

while(contactIterator.hasNext()) {
val contact = contactIterator.next(1).first()
prettyPrint(contact)
print("Press enter for next contact")
readln()
}

In this case, the filter method returns all the Contacts shared with the current user that have an encrypted link to one of the Patients passed as a parameter.

note

Since the link between Patient and Contact is encrypted, the user must also have access to the Patient to use this filter.

As with the previous example, the method returns an iterator that can be used to retrieve all the matching Contacts.

The additional information stored in an entity to provide additional context (like the identifiers in a Service) can also be used for filtering:

var choice = -1
while (choice < 0 || choice >= 3) {
println("0. blood pressure")
println("1. heart rate")
println("2. x ray")
print("Enter your choice: ")
choice = readln().trim().toIntOrNull() ?: 0
}

val identifier = when(choice) {
0 -> Identifier(system = "cardinal", value = "bloodPressure")
1 -> Identifier(system = "cardinal", value = "ecg")
2 -> Identifier(system = "cardinal", value = "xRay")
else -> throw IllegalArgumentException("Invalid choice")
}

val serviceIterator = sdk.contact.filterServicesBy(
ServiceFilters.byIdentifiersForSelf(listOf(identifier))
)

if (!serviceIterator.hasNext()) {
println("No matching services found")
}

while (serviceIterator.hasNext()) {
val service = serviceIterator.next(1).first()
prettyPrint(service)
print("Press enter for next service")
readln()
}

In this example, the filter method returns all the Services that have the provided identifier in the identifiers filter.