-
Notifications
You must be signed in to change notification settings - Fork 19
Implementing Search Indexing for a New Visualizer Type
When adding a new visualizer to the targeted data panel, the data of that visualizer must be indexed to be searchable. There are many example indexers to go off, but there are still a few important steps to follow in order to get the data to be searchable.
Visualizer type => Indexer
- NameValuePairsm => NameValuePairsIndexer
- NarrativeOnly => NameValuePairsIndexer
- Columns => ColumnsIndexer
- Events => EventsIndeser
- Medications => MedicationsIndexer
- ValueOverTime => ValueOverTimeIndeser
- ReviewOfSystemsValues => ReviewOfSystemsValuesIndexer
- ClusterPoints => ClusterPointsIndexer
This assumes you have already written a new visualizer for the targeted data panel, and that this visualizer has been added to the visualizers
array in VisualizerManager.jsx
as follow:
visualizers = [
/* other visualizers */
{ "dataType": "NewDataType", "visualizerType": "...", "visualizer": NewVisualizer }
];
Create a new file src/patientControl/NewIndexer.js
that extends BaseIndexer
:
import BaseIndexer from './BaseIndexer';
class NewIndexer extends BaseIndexer {
indexData(section, subsection, data, searchIndex, onHighlight) {
super.indexData(section, subsection, data, searchIndex, onHighlight);
}
}
export default NewIndexer;
The call to super.indexData
will index the section and subsection name.
There is a function in VisualizerManager.jsx
that returns the corresponding indexer to use based on the given dataType
. Add your indexer to the switch statement so its indexData
method gets called:
/* src/summary/VisualizerManager.jsx */
getIndexer(dataType) {
switch(dataType) {
case "NameValuePairs":
case "NarrativeOnly":
return new NameValuePairsIndexer();
case "Columns":
return new ColumnsIndexer();
case "Events":
return new EventsIndexer();
case "Medications":
return new MedicationsIndexer();
case "ValueOverTime":
return new ValueOverTimeIndexer();
case "DiseaseStatusValues":
return new DiseaseStatusValuesIndexer();
case "ReviewOfSystemsValues":
return new ReviewOfSystemsValuesIndexer();
case "ClusterPoints":
return new ClusterPointsIndexer();
case "TreatmentOptions":
return new BaseIndexer();
case "NewDataType": // Adding case for new indexer
return new NewIndexer();
default:
console.warn(`Targeted Data Panel data type '${dataType}' has no registered indexer.`);
return null;
}
}
Now that the indexer will be properly called to index the data of the new visualizer, you need to actually tell the search indexer to store relevant data from the visualizer in order for it to be searchable.
indexData
takes the following arguments:
-
section
: The name of the section for the data -
subsection
: The name of the relevant subsection (empty string if no subsection) -
data
: The data that gets rendered in the visualizer -
searchIndex
: A reference to the class inSearchIndex.js
. Used to make a call to actually index the data -
onHighlight
: Handler function for what happens when hovering over the search suggestion. For visualizers, this scrolls the data into view in the targeted data panel
For a given document (object that gets indexed), there are two fields that are searchable aside from the section name and subsection name (these are indexed by the base indexer): valueTitle
and value
. The valueTitle
is the "key" that describes the value
, e.g. for the data element "date" whose value is "1/1/2019", the valueTitle
would be "date" and the value
would be "1/1/2019"
An example of such a document would be the following:
{
id: "some_unique_id",
section: "Section Name",
subsection: "Subsection Name",
valueTitle: "Date",
value: "1/1/2019",
onHighlight: () => console.log('hello');
}
When this document gets indexed, the following search queries (or substrings of these queries) will result in this document being returned as a match:
- "Section Name" => matches on
section
field - "Subsection Name" => matches on
subsection
field - "Date" => matches on
valueTitle
field - "2019" => matches on
value
field
At a high level, implementation is done by calling searchIndex.addSearchableData
and passing in an object of the above form. The way our sections work in Flux Notes, the data
argument will either by an array or an object.
Iterate through what you need from the data
object, and make the above call with an object of the form of the example. There are many examples of this done in src/patientConrol
. Here is a simple example of how it could work:
import BaseIndexer from './BaseIndexer';
class NewIndexer extends BaseIndexer {
indexData(section, subsection, data, searchIndex, onHighlight) {
super.indexData(section, subsection, data, searchIndex, onHighlight);
const sectionId = super.getStringForId(section); // removes spaces and illegal characters and adds underscores
data.forEach(item => {
searchIndex.addSearchableData({
id: `${sectionId}_${item.foo}`, // uniquely identified by section name and valueTitle
section,
subsection,
valueTitle: item.foo,
value: item.bar,
onHighlight
});
});
}
}
export default NewIndexer;
Copyright © 2017 The MITRE Corporation | Approved for Public Release; Distribution Unlimited. Case Number 16‑1988
- Home
- About Flux Notes
- Active Treatment Summary Objects
- Data Standards for Breast Cancer
- Database decision
- Declarative Shortcut Format
- Demo Script
- Deployment Plan - Lite Mode
- Dragon Software Information and Troubleshooting
- Flux Notes Lite Demo Script
- How To Create New Shortcuts
- Interaction Between REACT.js Components in Flux
- JavaScript and HTML Code Style Guide
- Key Application Features
- Minimap Evaluation
- Naming Convention for Visual Components
- NLP Server: Provisioning and Troubleshooting
- Pre Release Testing Script
- Profiling and Performance
- Redux Implementation Guide
- Shorthand Context Problem
- Testing
- Third Party Libraries Changes
- Demo Scenarios -- (out of date)