Topics: |
An OmniCollection is a standard mechanism for depicting one-to-many relationships from one OmniObject to another. An OmniCollection contains a list of specific OmniObjects, also known as CollectionItems. The OmniCollection does not directly implement OmniElements or OmniGroups.
The following example shows the structure of an OmniCollection:
<!-OmniObjects defines the OmniCollection. --> <OmniObjects operation="<processing instruction>"> <!-Each OmniObject is a CollectionItem. --> <OmniObject > <SourceName>TestSource</SourceName> <SourceInstanceId>UniqueKey1</SourceInstanceId> <SourceModifiedDate format="yyyy-MM-dd">2013-01 01</SourceModifiedDate> </OmniObject> <OmniObject > <SourceName>TestSource</SourceName> <SourceInstanceId>UniqueKey2</SourceInstanceId> <SourceModifiedDate format="yyyy-MM-dd">2013-01- 01</SourceModifiedDate> </OmniObject> </OmniObject>
The operation attribute on an OmniCollection provides a processing instruction to Omni-Patient. The valid values for this attribute are described as follows:
Instructs Omni-Patient to delete all prior CollectionItems and insert the new ones provided.
Instructs Omni-Patient to use a SQL Merge, or "upsert", for the new CollectionItems provided. If the CollectionItem exists on the database, it will be updated. If it does not currently exist, it will be inserted. Any previously loaded CollectionItem that does not appear in the new list will remain unchanged on the database. This is considered the default operation.
During an update operation, it may become necessary to clear the contents of an OmniCollection. The technique that is used to communicate the clearing of an OmniCollection is to send an empty OmniCollection node, as shown in the following example.
<!-An empty OmniObject will clear the contents of an OmniCollection. --> <OmniObjects />
Topics: |
As stated earlier, a CollectionItem is simply one of the OmniObject children of an OmniCollection. Since a CollectionItem is an OmniObject, the choice of SourceInstanceId presents some unique considerations.
The following is an example of a CollectionItem.
<Patient> <SourceName>TestSource</SourceName> <SourceInstanceId>Patient|12345678</SourceInstanceId> <Person> <Person> <!-Same SourceInstanceId as parent helps assist with traceability. --> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678</SourceInstanceId> <SourceModifiedDate format="yyyy-MM-dd">2013-01- 01</SourceModifiedDate> <!- PersonIdentifiers is an OmniCollection. --> <PersonIdentifiers> <!- PersonIdentifier is a CollectionItem. --> <PersonIdentifier> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|<Discriminator1></SourceInstanceId> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>12345678</Value> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01</SourceModifiedDate> </PersonIdentifier> <!- PersonIdentifier is a CollectionItem. --> <PersonIdentifier> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|<Discriminator2></SourceInstanceId> <Type sourceName="OMNI" sourceCode="SS" sourceCodeSet="0001"/> <Value>123-45-6789</Value> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01</SourceModifiedDate> </PersonIdentifier> </PersonIdentifiers> </Person> </Person> </Patient>
In order to uniquely identify a CollectionItem in Omni-Patient, it is recommended to identify the string of parent OmniObjects all the way up to the Subject, in addition to some type of discriminator that uniquely identifies one CollectionItem from another.
The recommendation is that the SourceInstanceId for a CollectionItem follow the pattern:
ParentObject.SourceInstanceId<Separator> Object<Separator> CollectionItemDiscriminator
The recommended implementation of SourceInstanceId for a CollectionItem is shown in the following example:
<Patient> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678</SourceInstanceId> <Person> <Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC</SourceInstanceId> <SourceModifiedDate format="yyyy-MM-dd">2013-01-01</SourceModifiedDate> <PersonIdentifiers> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- Concatenate the Discriminator to the Patient's SourceInstanceId.--> <SourceInstanceId> Patient|12345678|Person|ABC|PersonIdentifier|<Discriminator1> </SourceInstanceId> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>12345678</Value> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01</SourceModifiedDate> </PersonIdentifier> </PersonIdentifiers> </Person> </Person> </Patient>
The non-recommended implementation of SourceInstanceId for a CollectionItem is shown in the following example:
<Patient>
<SourceName>TestSource</SourceName>
<SourceInstanceId> Patient|12345678</SourceInstanceId>
<Person>
<Person>
<SourceName>TestSource</SourceName>
<SourceInstanceId> Patient|12345678|Person|ABC</SourceInstanceId>
<SourceModifiedDate format="yyyy-MM-dd">2013-01-01</SourceModifiedDate>
<PersonIdentifiers>
<PersonIdentifier>
<SourceName>TestSource</SourceName>
<!- Without the Parent Object's SourceInstanceId, there is nothing to
differentiate Discriminator1 across multiple Patients. -->
<SourceInstanceId> PersonIdentifier|<Discriminator1> </SourceInstanceId> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>12345678</Value> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01</SourceModifiedDate> </PersonIdentifier> </PersonIdentifiers> </Person> </Person> </Patient> <Patient> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|23456789</SourceInstanceId> <Person> <Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|23456789|Person|ABC</SourceInstanceId> <SourceModifiedDate format="yyyy-MM-dd">2013-01- 01</SourceModifiedDate> <PersonIdentifiers> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- Without the Parent Object's SourceInstanceId, there is nothing to differentiate Discriminator1 across multiple Patients. The result is that this identifier will be repeatedly updated across all Patients. --> <SourceInstanceId> PersonIdentifier|<Discriminator1> </SourceInstanceId> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>23456789</Value> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01 </SourceModifiedDate> </PersonIdentifier> </PersonIdentifiers> </Person> </Person> </Patient>
The selection of the CollectionItem Discriminator depends on how the CollectionItem is implemented in the SourceSystem.
Often there will be a CollectionItem Type that will help differentiate one CollectionItem from another. In the cases where one and only one record of a certain CollectionItem Type is expected, the value of the Type code can be utilized as the Discriminator.
Note: The following examples have been reduced to relevant data elements for brevity.
The recommended implementation of a CollectionItem Discriminator selection is shown in the following example:
<Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC</SourceInstanceId> <PersonIdentifiers> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- When there is one and only one of each sourceCode value is expected for the Type, the sourceCode value may be used as the Discriminator. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonIdentifier Discriminator = MR --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonIdentifier|MR </SourceInstanceId> <!- The sourceCode value below is used as the Discriminator in the SourceInstanceId --> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>12345678</Value> </PersonIdentifier> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- When there is one and only one of each sourceCode value is expected for the Type, the sourceCode value may be used as the Discriminator. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonIdentifier Discriminator = SS --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonIdentifier|SS</SourceInstanceId> <!- The sourceCode value below is used as the Discriminator in the SourceInstanceId --> <Type sourceName="OMNI" sourceCode="SS" sourceCodeSet="0001"/> <Value>123-45-6789</Value> </PersonIdentifier> </PersonIdentifiers> </Person>
The non-recommended implementation of a CollectionItem Discriminator selection is shown in the following example:
<Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC</SourceInstanceId> <PersonIdentifiers> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- Lack of a Discriminator in the SourceInstanceId will result in only one PersonIdentifier being created. It will get consistently over-written with each subsequent identifier. --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonIdentifier </SourceInstanceId> <Type sourceName="OMNI" sourceCode="MR" sourceCodeSet="0001"/> <Value>12345678</Value> </PersonIdentifier> <PersonIdentifier> <SourceName>TestSource</SourceName> <!- Lack of a Discriminator in the SourceInstanceId will result in only one PersonIdentifier being created. It will get consistently over-written with each subsequent identifier. --> <SourceInstanceId> Patient|12345678|Person|ABC |PersonIdentifier </SourceInstanceId> <Type sourceName="OMNI" sourceCode="SS" sourceCodeSet="0001"/> <Value>123-45-6789</Value> </PersonIdentifier> </PersonIdentifiers> </Person>
Many times, the CollectionItem Type alone may not function as enough of a discriminator. For example, if the source system allows for multiple PersonNames with the type Alias, an additional value must be selected to further distinguish the two Alias records. If there is another business value discriminator that can be used, it's best. However, if that is unavailable, a numeric order may be concatenated, so long as it is consistently repeatable for the same logical record(s).
The recommended implementation is shown in the following example:
<Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC</SourceInstanceId> <PersonNames> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, an additional value is necessary on the Discriminator to further distinguish the records. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonName Discriminator = A1 --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A1 </SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0200"/> <FullName>John Doe</FullName> </PersonName> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, an additional value is necessary on the Discriminator to further distinguish the records. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonName Discriminator = A2 --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A2</SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0001"/> <FullName>John Q Public</FullName> </PersonName> </PersonNames> </Person>
<!- In the following scenario, a PersonName update for "John Q. Public" (as represented by the "A2" Discriminator) is sent as an update. In this case, "John Quincy Public" updates the "John Q Public" record, resulting in one record for "John Quincy Public" and another for "John Doe", sent previously above. --> <Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC </SourceInstanceId> <PersonNames> <PersonName> <SourceName>TestSource</SourceName> <!- Update of the John Q Public record above --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A2</SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0001"/> <FullName>John Quincy Public</FullName> </PersonName> </PersonNames> </Person>
The non-recommended implementation is shown in the following example:
<Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC </SourceInstanceId> <PersonNames> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, the sourceCode value may not be solely used as the Discriminator. It will result in a single record being created for each sourceCode value ('A') in this case. This record will get consistently over-written with each subsequent identifier. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonName Discriminator = A -->
<SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A</SourceInstanceId> <!- The sourceCode value below is used as the Discriminator in the SourceInstanceId --> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0200"/> <FullName>John Doe</FullName> </PersonName> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, the sourceCode value may not be solely used as the Discriminator. It will result in a single record being created for each sourceCode value. This record will get consistently over-written with each subsequent identifier. Parent Obect's SourceInstanceId = Patient|12345678|Person|ABC Object = PersonName Discriminator = A (same as the PersonName record above) --><SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A </SourceInstanceId> <!- The sourceCode value below is used as the Discriminator in the SourceInstanceId --> < Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0001"/> <FullName>John Q Public</FullName> </PersonName> </PersonNames> </Person> <!- In the following scenario, a PersonName update for "John Q. Public" is sent with a different Discriminator the second time through ("A1" vs. "A2"). In this case, "John Quincy Public" updates the "John Doe" record, rather than the intended "John Q. Public" record, resulting in one record for "John Quincy Public" and another for "John Q. Public". The "John Doe" record will only exist in the history tables for the "John Quincy Public" record. --> <Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC </SourceInstanceId> <PersonNames> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, an additional value is necessary on the Discriminator to further distinguish the records. --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A1</SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0200"/> <FullName>John Doe</FullName> </PersonName> <PersonName> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, an additional value is necessary on the Discriminator to further distinguish the records. --> <SourceInstanceId> Patient|12345678|Person|ABC|PersonName|A2</SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0001"/> <FullName>John Q Public</FullName> </PersonName> </PersonNames> </Person> <Person> <SourceName>TestSource</SourceName> <SourceInstanceId> Patient|12345678|Person|ABC </SourceInstanceId> <PersonNames> <PersonName> <SourceName>TestSource</SourceName> <!- This update is sent with "John Doe's" Discriminator. This will have the unintended effect of updating the "John Doe" record (A1), rather than the "John Q Public" record (A2). --> <SourceInstanceId> Patient|12345678|Person|ABC| PersonName|A1</SourceInstanceId> <Type sourceName="OMNI" sourceCode="A" sourceCodeSet="0001"/> <FullName>John Quincy Public</FullName> </PersonName> </PersonNames> </Person>
In some cases, the CollectionItem does not have a Type, but there may be other data element(s) that serve as a discriminator for the CollectionItem. In the example below, the ProviderPracticeSpecialties are differentiated by the Facility at which the Specialty is practiced.
The recommended implementation is shown in the following example:
<Provider> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider |12345678</SourceInstanceId> <ProviderSpecialties> <ProviderSpecialty> <SourceName>TestSource</SourceName> <!- When more than one of a each sourceCode value is expected for the Type, an additional value is necessary on the Discriminator to further distinguish the records. <SourceInstanceId> Provider |12345678|ProviderSpecialty|261QA1903X </SourceInstanceId>
<SpecialtyType sourceName="OMNI" sourceCode=" 261QA1903X" sourceCodeSet="0454"/> <PracticingSpecialties> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName> <!- When there is noType, another data element value can serve as the Discriminator for the record. Parent Obect's SourceInstanceId = Provider|12345678|ProviderSpecialty|261QA1903X Object = ProviderPracticeSpecialty Discriminator = Facility1 --> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|Facility1 </SourceInstanceId> <!- This is an OmniLink to the Facility at which the Provider practices this specialty. The Facility data element contains a reference to a Facility OmniObject.--> <Facility> <Facility> <SourceName>TestSource</SourceName> <!- The Facility at which the Provider practices this specialty is used as the Discriminator.--> <SourceInstanceId> Facility:Facility1 </SourceInstanceId> </Facility> </Facility> </ProviderPracticeSpecialty> </PracticingSpecialties > </ ProviderSpecialty> </ ProviderSpecialties > </ Provider > <!- In the following scenario, an attempt is made to use an Alphabetic sort order of the Facility Name as a Discriminator. This is not recommended if another business key is available because it may be difficult to replicate when new records are introduced. In the example Facility "B" is inserted after Facility "A" and Facility "C" were loaded previously. This changes the sort order and makes history a little more difficult to understand. -->
The non-recommended implementation is shown in the following example:
<Provider> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider |12345678</SourceInstanceId> <ProviderSpecialties> <ProviderSpecialty> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider |12345678|ProviderSpecialty| 261QA1903X </SourceInstanceId> <SpecialtyType sourceName="OMNI" sourceCode=" 261QA1903X" sourceCodeSet="0454"/> <PracticingSpecialties> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName> <!- When there is noType, another data element value can serve as the Discriminator for the record. Parent Obect's SourceInstanceId = Provider|12345678|ProviderSpecialty|261QA1903X Object = ProviderPracticeSpecialty Discriminator = 1 --> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|1 </SourceInstanceId> <!- This is an OmniLink to the FacilityLocation at which the Provider practices this specialty. The Facility data element contains a reference to a Facility OmniObject.--> <Facility> <Facility> <SourceName>TestSource</SourceName> <!- The Facility at which the Provider practices this specialty is used as the Discriminator.--> <SourceInstanceId> Facility:FacilityA </SourceInstanceId> </Facility> </Facility> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01 </SourceModifiedDate> </ProviderPracticeSpecialty> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName>
<!- When there is noType, another data element value can serve as the Discriminator for the record. Parent Obect's SourceInstanceId = Provider|12345678|ProviderSpecialty|261QA1903X Object = ProviderPracticeSpecialty Discriminator = 2 --> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|2 </SourceInstanceId> <Facility> <Facility> <SourceName>TestSource</SourceName> <SourceInstanceId> Facility:FacilityC </SourceInstanceId> </Facility> </Facility> <SourceModifiedDate format="yyyy-MM-dd"> 2013-01-01 </SourceModifiedDate> </ProviderPracticeSpecialty> </PracticingSpecialties > </ ProviderSpecialty> </ ProviderSpecialties > </ Provider > <!- Update of the ProviderPracticeSpecialties, inserting Facility "B" as a new Facility at which the Specialty is being practiced by the Provider (in addition to Facility "A" and Facility "C").--> <Provider> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider |12345678</SourceInstanceId> <ProviderSpecialties> <ProviderSpecialty> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider |12345678|ProviderSpecialty| 261QA1903X </SourceInstanceId> <SpecialtyType sourceName="OMNI" sourceCode=" 261QA1903X" sourceCodeSet="0454"/> <PracticingSpecialties> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|1 </SourceInstanceId> <Facility>
<Facility> <SourceName>TestSource</SourceName> <SourceInstanceId> Facility:FacilityA </SourceInstanceId> </Facility> </Facility> <SourceModifiedDate format="yyyy-MM-dd"> 2013-02-01 </SourceModifiedDate> </ProviderPracticeSpecialty> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|2 </SourceInstanceId> <Facility> <Facility> <SourceName>TestSource</SourceName> <SourceInstanceId> Facility:FacilityB </SourceInstanceId> </Facility> </Facility> <SourceModifiedDate format="yyyy-MM-dd"> 2013-02-01 </SourceModifiedDate> </ProviderPracticeSpecialty> <ProviderPracticeSpecialty> <SourceName>TestSource</SourceName> <SourceInstanceId> Provider|12345678|ProviderSpecialty|261QA1903X|ProviderPracticeSpecialty|3 </SourceInstanceId> <Facility> <Facility> <SourceName>TestSource</SourceName> <SourceInstanceId> Facility:FacilityC </SourceInstanceId> </Facility> </Facility> <SourceModifiedDate format="yyyy-MM-dd"> 2013-02-01 </SourceModifiedDate> </ProviderPracticeSpecialty> </PracticingSpecialties > </ ProviderSpecialty> </ ProviderSpecialties > </ Provider >
A summarization of the history records, as a result of loading these ProviderPracticeSpecialties, is indicated below. An unpopulated EndDate in a history table indicates the current record. Please note in the update that Facility "C" changes from being referenced by Discriminator "2" to Discriminator "3". In order to understand how long the Provider has been practicing the Specialty at Facility "C", one would need to calculate across multiple objects.
Initial Load
Object + Discriminator |
Facility |
Hist_StartDate |
Hist_EndDate |
---|---|---|---|
ProviderPracticeSpecialty|1 |
A |
2013-01-01 |
|
ProviderPracticeSpecialty|2 |
C |
2013-01-01 |
Update
Object + Discriminator |
Facility |
Hist_StartDate |
Hist_EndDate |
---|---|---|---|
ProviderPracticeSpecialty|1 |
A |
2013-01-01 |
2013-02-01 |
ProviderPracticeSpecialty|1 |
A |
2013-01-01 |
|
ProviderPracticeSpecialty|2 |
C |
2013-01-01 |
2013-02-01 |
ProviderPracticeSpecialty|2 |
B |
2013-01-01 |
|
ProviderPracticeSpecialty|3 |
C |
2013-01-01 |