HealthVault Data Type Awesomeness
Warning: Geek post alert.
Late last week I got an email from a customer asking some questions about how HealthVault renders data types at http://healthvault.com. As I answered the question, I realized that I haven’t ever really talked here about all the incredible richness underlying the HealthVault data type system. So here goes.
HealthVault records are made up of a collection of items. Each item has a “type” --- for example, a Blood Pressure Measurement or a Continuity of Care Record document. Each item consists of an XML document and, in cases such as medical images, one or more associated binary streams. The XML is constrained by a per-type “schema” that defines the required and optional data elements for the type. For example, a blood pressure must have systolic and diastolic measurements, but it may or may not store a pulse.
There are dozens of item types in the HealthVault system, and we add and update them all the time. This agility has served us well --- it’s why we’ve been able to easily extend HealthVault to include things such as Genetic SNPs, medical image studies and EOB documents. But that’s just the surface of the awesomeness.
HealthVault exposes all of the information about data types through the public API. Most of it is available on the web on MSDN, but for the purposes of this article (and my own amusement) I wrote a little command-line utility to help you explore what’s in there. The source and binary download for this guy are at the end of this post.
Sometimes just working within HealthVault XML data “as-is” is good enough. But often, folks want to do something specific, like:
- Render items as HTML
- Render tables and lists of items
- Convert items to or from a standard like CCR or CCD
Well guess what –- HealthVault to the rescue! Each data type has a set of associated XSLT “transforms” that are accessible through the SDK and can be used to re-shape the data for any of these purposes. In fact, when you execute a query for HealthVault data, you can ask to have it auto-transformed for you just by specifying the name of one of them (or you can even supply your own XSLT).
This is SUPER powerful and we use it all over the place. You’ll find transforms that convert items from WPD format for device data, to RSS for use in syndication feeds --- we even drive the “reconciliation” process using transforms that turn composite documents like CCR into native HealthVault items.
It also means that applications can render items without knowing anything about what’s really inside them. This can come in awfully handy … on healthvault.com, we have one routine that renders the tables and details views for all types, just using different transforms.
HealthVault records are meant to last a lifetime --- when my kids head off to college, I fully expect them to take their records with them. But our understanding of health information is changing all the time --- how can we ensure that data created in 2007 is still usable and valuable in 2027? And how can I ensure that applications I use now can keep working even as the data type library changes underneath them?
This is a wicked nasty problem. Transforms to the rescue again!
Each data type can have multiple versions, and each has “upversion” and “downversion” transforms that know how to convert between them. Because HealthVault applications register which versions of types they know how to deal with, we can automatically do magic behind the scenes to ensure that apps only see the right versions. Old apps keep working with new data, and new apps keep working with old data. Cool!
Of course, there are some restrictions involved here --- for example, it’s quite difficult for us to make a required element optional in a new version. But in general, the system works great … and gives us a ton of flexibility to improve types without causing ecosystem chaos.
Versioning is perhaps my favorite example of how HealthVault really nails the details that others don’t even think about. And the details matter a lot in health.
The hits keep coming
HealthVault data types support digital signatures on items, which allows us to support the concept of “provider trust” even though the channel is completely consumer-controlled.
Our query model leverages the fact that we store items as XML to support a rich query language. For example, it’s really easy to use XPath queries to fetch only Blood Pressures with Systolic measurements over 120, or medications that are active, or… you name it.
Data types can also be extended --- every item can hold “application-specific” XML that can be uniquely addressed. Polar watches make great use of this in Exercise items --- they add a ton of additional details as part of the data they upload.
And a ton more. I give up trying to cram it all into one post. While we often talk about HealthVault as just a vehicle for “gets” and “puts” --- there is all kinds of power at the next level of detail. Play around at MSDN, and if you have questions --- check out the forums or just drop me a note!
Appendix: hvtypeinfo.exe details
This is just a baby console app I put together to make it easy to query details of the HealthVault data type system. You can download the source or binary files to play with it --- but no warranties or guarantees about how they’ll work. No need to “install” the binary version, just extract the files to a directory and run them from there.
Usage: hvtypeinfo.exe vocab
Prints list of all vocabularies in system
Usage: hvtypeinfo.exe vocab [name]
Prints vocabulary summary and all item/display combinations for 'name'
Use 'thing-types' to retrieve all data types in system
Usage: hvtypeinfo.exe vocab [name] [family] [version]
Prints vocabulary summary and all item/display combinations
for specified vocab (might be long!)
Usage: hvtypeinfo.exe type [id/name]
Shows summary information about type
Usage: hvtypeinfo.exe type [id/name] schema
Returns XSD for type
Usage: hvtypeinfo.exe type [id/name] columns
Returns Single-type Table column definitions for type
Usage: hvtypeinfo.exe type [id/name] [transform-name]
Returns XSLT for given 'transform-name'