Статьи

Мультитенантные графовые приложения

Примечание редактора:

 

Многоквартирный программная система представляет собой систему , которая поддерживает любое количество клиентов в пределах одного экземпляра приложения. Как правило, этот единственный экземпляр использует общий набор данных, где данные клиента должным образом отделены от данных другого. Хотя разделение данных является важнейшим аспектом многопользовательского приложения, могут существовать общесистемные (например, глобальные) вычисления, которые требуют потребления всех данных клиента (или некоторого их подмножества). Если такие глобальные операции не требуются, то многопользовательское приложение вместо этого будет приложением с несколькими экземплярами, в котором данные каждого клиента содержатся в отдельном изолированном хранилище. Несколько примеров приложений с несколькими арендаторами перечислены ниже.

  • Конфиденциальные отчеты компании (например, рыночные стратегии или финансовая информация) в системе бизнес-аналитики изолированы от конкурентов в рамках одного приложения. Однако общедоступные данные (например , данные переписи, рынка, налоговые данные) распределяются между различными наборами данных арендаторов и связываются между ними. Таким образом, общедоступные данные помогают повысить полезность соответствующих частных данных каждой компании.
  • Социальная сеть гарантирует конфиденциальность пользователей , а, в список управления доступом (ACL) способе, позволяет пользователям обмениваться данными с другими доверенными пользователями (например , друзьями) в системе.
  • Записи пациентов в многопользовательской электронной системе медицинских записей могут быть разделены для обеспечения конфиденциальности пациента. Тем не менее, можно собрать коллективную статистику из глобального набора данных, чтобы аналитики / ученые, работающие с данными, могли изучить проблемы здоровья населения в целом.

Чертежи и PartitionGraph

TinkerPop в светокопиях 1.2+ позволяет легко построить, Многоквартирные график на основе приложений. Blueprints представляет собой базу данных граф интерфейс похож на JDBC из реляционной базы данных сообщества. Чертежи поддерживаются различными графическими базами данных, включая TinkerGraph , Neo4j , OrientDB , DEX и InfiniteGraph . В дополнение к предоставлению стандартного графического интерфейса, Blueprints включает в себя коллекцию графических оболочек. Оболочка графа берет существующую реализацию графа, такую ​​как Neo4jGraph, и украшает ее новыми функциями. Например, оборачивая реализацию графаReadOnlyGraph предотвращает мутации графа.

Графическая оболочка, которая обеспечивает многопользовательский режим, называется PartitionGraph . PartitionGraph разделяет нижележащий граф на разные секции / сегменты. Однако ребра могут связывать вершины в двух отдельных разбиениях. Таким образом, мультитенантность четко реализована, когда раздел служит местом хранения данных одного арендатора. Более того, «перекрестное удобрение» данных возможно благодаря соответствующим ограниченным связям между разделами. Дизайн PartitionGraph сильно заимствует из архитектуры данных Named Graph, популяризированной сообществом Web of Data / Linked Data . Оставшаяся часть этого поста будет демонстрировать многопрофильность на основе графиков посредством электронных медицинских карт.(EHR) системный пример с использованием PartitionGraph, языка обхода / запроса графов Gremlin и красочных символов TinkerPop .

Внутрираздельные электронные медицинские карты

Следующий фрагмент кода демонстрирует, как PartitionGraph решает проблему многопользовательской работы. Сначала строится новый граф, который оборачивается в PartitionGraph с начальным разделом записи pgp (Pipes General Practice). График используется в памяти TinkerGraph. Раздел записи — это раздел, в который записываются вновь созданные данные. Когда пациент Гремлин обращается в Pipes General Practice и TinkerPop Medical Center, две вершины записываются в разделы pgp и tmc соответственно.

~$ gremlin

         \,,,/
         (o o)
-----oOOo-(_)-oOOo-----
gremlin> g = new PartitionGraph(new TinkerGraph(), '_partition', 'pgp')
==>partitiongraph[tinkergraph[vertices:0 edges:0]]
gremlin> g.getPartitionKey() 
==>_partition
gremlin> g.getReadPartitions()    
==>pgp
gremlin> g.getWritePartition()
==>pgp
gremlin> gremlinPgp = g.addVertex('gremlin@pipesgeneralpractice')
==>v[gremlin@pipesgeneralpractice]
gremlin> g.setWritePartition('tmc')
gremlin> gremlinTmc = g.addVertex('gremlin@tinkerpopmedicalcenter')
==>v[gremlin@tinkerpopmedicalcenter]

Следующая диаграмма показывает, что было установлено до сих пор. В одном многопользовательском графе есть два раздела (pgp и tmc). Гремлин посетил оба объекта и имеет две разные истории болезни, обозначенные вершинами и ребрами внутри каждого раздела. Обратите внимание, что создание этих медицинских историй не продемонстрировано в фрагменте кода выше. Для ясности представьте, что история болезни включает в себя текущие состояния пациента, результаты лабораторных исследований, жизненно важные органы (такие как рост, вес и артериальное давление), аллергии, текущие лекарства и т. Д.

Когда врач в Pipes General Practice проверяет записи пациентов (где PartitionGraph имеет раздел чтения, установленный в pgp), врач будет видеть только данные Pipes General Practice. Более того, если текущий раздел чтения удаляется и добавляется новый, то видны только данные в новом добавленном разделе.

gremlin> g.V
==>v[gremlin@pipesgeneralpractice]
gremlin> g.removeReadPartition('pgp')
gremlin> g.addReadPartition('tmc')
gremlin> g.V
==>v[gremlin@tinkerpopmedicalcenter]

На этом этапе в примере показано, как защитить данные клиента с помощью PartitionGraph. Далее можно выйти за рамки простого разделения элементов графа на разбиения. Ребра могут быть как внутри-, так и межраздельными, поскольку они могут указывать на вершины в одном и том же разделе или на вершины в двух разных разделах. Таким образом, можно вводить глобальные данные, которые могут использоваться всеми клиентами.

Межотраслевые электронные медицинские карты

Следующий фрагмент кода представляет новый раздел snomed, где snomed ссылается на общедоступный набор данных клинических терминов SNOMED-CT . Примеры терминов включают пневмонию , простуду , острый носовой катар и т. Д. Вершины и ребра добавляются к разделу с нюхом, который представляет иерархию понятий SNOMED-CT. Обратите внимание, что на практике полный набор данных SNOMED-CT будет разбираться в разделе, но для этого простого примера записываются два клинических термина и их отношение подстановки .

gremlin> g.setWritePartition('snomed')
gremlin> painInRightLeg = g.addVertex('snomed:287048003', [name:'Pain in right leg (finding)'])
==>v[snomed:287048003]
gremlin> painInLowerLimb = g.addVertex('snomed:10601006', [name:'Pain in lower limb (finding)'])
==>v[snomed:10601006]
gremlin> g.addEdge(painInRightLeg, painInLowerLimb, 'broader')
==>e[0][snomed:287048003-broader->snomed:10601006]

 Когда пациент Гремлин жалуется на травмированную ногу как в Pipes General Practice, так и в TinkerPop Medical Center, добавляются ребра, которые соединяют вершину пациента с соответствующей вершиной клинического термина в разрезанной части. Эти отмеченные ребрами обозначены пунктирными линиями на диаграмме ниже.

gremlin> g.setWritePartition('pgp')
gremlin> g.addEdge(gremlinPgp, painInRightLeg, 'complainedOf')
==>e[1][gremlin@pipesgeneralpractice-complainedOf->snomed:287048003]
gremlin> g.setWritePartition('tmc')
gremlin> g.addEdge(gremlinTmc, painInRightLeg, 'complainedOf')
==>e[2][gremlin@tinkerpopmedicalcenter-complainedOf->snomed:287048003]

Что касается диаграммы ниже, предположим, что и Rexster, и Frames являются новыми пациентами в медицинском центре TinkerPop , которые также жаловались на боль в конечностях. Специалист по боли в конечностях в Медицинском центре TinkerPop может запросить раздел TMC, чтобы узнать, у каких пациентов есть проблемы с нижними конечностями. Обход в строке 2 идет по иерархии SNOMED-CT, чтобы найти всех пациентов в разделе tmc, которые жаловались на что-либо, связанное с болью в нижней конечности (например, боль в правой ноге). Учитывая более сложную иерархию, при этом обходе графа могут быть выявлены различные заболевания нижних конечностей и пациенты, страдающие такими заболеваниями.

gremlin> g.addReadPartition('snomed')
gremlin> painInLowerLimb.in('broader').loop(1){true}{it.object.in('complainedOf').count() > 0}.in('complainedOf')
==>v[gremlin@tinkerpopmedicalcenter]
==>v[rexster@tinkerpopmedicalcenter]
==>v[frames@tinkerpopmedicalcenter]

В расширенном наборе данных EHR могут быть приняты различные другие типы графовых запросов. Несколько примеров приведены ниже.

  • Определите, какие методы лечения применялись у пациентов, страдающих той же болезнью нижней конечности, что и Гремлин.
  • Сопоставьте личную историю болезни всех пациентов с нижними конечностями, чтобы увидеть, есть ли между ними связь (например, курение, ожирение, рецепты врачей и т. Д.).
  • Найдите соответствующие клинические термины в SNOMED-CT и найдите других пациентов, у которых есть похожие проблемы (например, онемение ноги, ишиас и т. Д.). Определите, какие методы лечения были успешными для этих связанных пациентов.
  • Соедините записи пациента Гремлина в Медицинском центре Пайпс и в Медицинском центре ТинкерПоп, чтобы создать единую перспективу истории болезни Гремлин через кромку sameAs (представленную пунктирной линией на диаграмме выше).

Вывод

Преимущество PartitionGraph заключается в том, что глобальные данные не вносят существенной сложности в модель программирования и не представляют опасности для разделенных перегородками разделов. Кроме того, можно провести анализ всего графа, охватывающий все разделы. Это может быть неоспоримым преимуществом для приложений бизнес-аналитики. Учитывая текущий пример, просто делая все разделы читаемыми, можно анализировать медицинские истории во всех медицинских учреждениях и использовать данные SNOMED-CT в качестве моста между этими, казалось бы, разрозненными многораздельными наборами данных.

gremlin> g.addReadPartition('pgp')
gremlin> g.addReadPartition('tmc')
gremlin> g.addReadPartition('snomed')
gremlin> g.V
==>v[rexster@tinkerpopmedicalcenter]
==>v[snomed:287048003]
==>v[frames@tinkerpopmedicalcenter]
==>v[snomed:10601006]
==>v[gremlin@tinkerpopmedicalcenter]
==>v[gremlin@pipesgeneralpractice]
gremlin> g.E
==>e[3][rexster@tinkerpopmedicalcenter-complainedOf->snomed:287048003]
==>e[2][gremlin@tinkerpopmedicalcenter-complainedOf->snomed:287048003]
==>e[1][gremlin@pipesgeneralpractice-complainedOf->snomed:287048003]
==>e[0][snomed:287048003-broader->snomed:10601006]
==>e[4][gremlin@tinkerpopmedicalcenter-sameAs->gremlin@pipesgeneralpractice]
==>e[5][frames@tinkerpopmedicalcenter-complainedOf->snomed:287048003]

PartitionGraph предоставляет интересные возможности для анализа, который смешивает и сопоставляет различные разделы в пространстве обхода. В заключение, представлен набор более сложных случаев использования ЭМК в медицинских целях, которым PartitionGraph удобно воспользоваться.

  • Анализ перекрестного медицинского учреждения (т. Е. Разделения) показывает, что процент пациентов с ВИЧ / СПИДом, которым назначены антиретровирусные препараты, не соответствует стандартам, установленным в центрах качества центров Medicare и Medicaid Services (CMS) . Этот анализ побуждает медицинских работников и администраторов рассмотреть изменения в протоколах лечения и формулярах лекарств.
  • Сообщества врачей могут быть определены путем анализа визитов пациентов и схем лечения. Учитывая эти сообщества, фармацевтические компании могут предсказать влияние влиятельных людей в социальной сети, чтобы получить представление о потенциальных моделях принятия лекарств.
  • Записи пациентов во всех разделах предоставляют основополагающий набор данных для анализа среди населения в рамках системы поддержки принятия клинических решений .