对于患者而言,了解医疗保健领域可能令人困惑。术语和选择通常不熟悉,甚至很难弄清楚如何开始。零售网站上常见的“商店查找”功能可以通过输入邮政编码或区号,帮助您找到附近附近的医生或其他医疗保健提供者。
遗憾的是,难以构建始终适用的该功能。我们生活在一个球体上,如果我们想要查找各个方向中特定距离内的位置,则必须将一个圆投影到一个球体上,并使用一个不太简单的坐标系。所有这些都等同于不那么简单的数学运算。谢天谢地,Redis 拥有各种各样的地理空间功能,可以帮助你构建此类功能。
我们在本问题中回答过的基本问题非常简单:“什么医疗机构离我最近?”为了执行此操作,你需要医疗机构的列表、医疗机构的经度和纬度位置,以及提出问题的患者的位置。医疗机构的列表可能如下所示:
这是一个用于演示的小型列表,但此列表在 Redis 中可能非常庞大,仅受可用内存量的限制。
查找患者位置的方法有许多:反向 IP、邮政编码匹配(称为地理编码器),甚至是设备 GPS。每种方法都有优缺点,以及超出本文讨论范围的特定实施详细信息。但是,无论哪种方法,它们都解决经纬度问题。我们现在假设位置为 53.5469,-113.4977。
将数据放入 Redis 可以是一次性事务,也可以随着医疗机构列表发生更改而定期更新。GEOADD命令将位置添加到地理位置集中。地理位置集是已将经度和纬度编码到一个 GeoHash 中的已排序集的变体,该 GeoHash 存储在已排序集合成员的分数中。我们来看看它看起来像什么样子:
> GEOADD 医疗机构 -113.4967 53.5574 皇家亚历克斯
(整型) 1
> GEOADD 医疗机构 -113.5313 53.5177 十字癌症研究所
(整型) 1
> GEOADD 医疗机构 -113.4283 53.4608 格雷修女社区医院
(整型) 1
> GEOADD 医疗机构 -113.5247 53.5205 阿尔伯塔大学医院
(整型) 1
> GEOADD 医疗机构 -113.6119 53.5207 慈悲社区医院
(整型) 1
此示例中的重要内容是参数。第一个参数是键,在 Redis 中很常见。第二个参数是经度,第三个参数是纬度,最后是成员。(非常重要的一点是要注意经度和纬度的顺序与你可能习惯看到的顺序相反。)
现在,我们将数据放入系统后,每当用户想查找提供商时,我们只需运行一个 Redis 命令就可以找到离他们很近的位置:
> GEORADIUS 医疗机构 -113.4977 53.5469 5 km
第一个参数是我们之前的同一个密钥,第二个和第三个参数是用户的经度和纬度(分别)。第四个和第五个参数是距离和单位(km 代表公里,mi 代表英里,f 代表英尺和,m 代表米)。输出结果如下:
1) "royal-alex"
2) "university-of-alberta-hospital"
3) "cross-cancer-institute"
上面的示例能让患者找到最近的医疗保健机构,但如果他们想去找一家提供特定服务的服务商该怎么办?如果他们需要一个提供不止一种专科服务的机构,该怎么办?Redis 也可以在这方面提供帮助。
不用 GEO 命令族,我们将使用 搜索和查询 模块。搜索和查询具有更丰富的查询数据的能力,但保留了 GEO 命令族的地缘空间功能。但是,这些更丰富的功能需要我们先创建一个模式。
> FT.CREATE ft_providers SCHEMA name TEXT services TAG location GEO
这将创建一个包含三个字段的索引,名为 ft_providers: name、services和 location。 name是文本字段,因此它可以容纳人类语言; services是一个标记字段,它保存代表所提供服务的标记;最后,location 保存位置的纬度和经度。
现在,让我们将我们的位置添加到索引中。我们将使用 FT.ADD 命令,它需要索引,然后需要一个文档 ID 来唯一识别文档,再然后需要一个文档得分。在此之后,SCHEMA 保留字将选项与文档的字段区分开来,按照字段名称、值的顺序排列。我们来看看:
> FT.ADD ft_providers royal-alex 1.0 FIELDS name "Royal Alex Hospital" services "kidneyclinic,footclinic,gastroscopy,geriatrics,intensivecare,plasticsurgery,ultrasound" location "-113.4967 53.5574" OK > FT.ADD ft_providers cross-cancer-institute 1.0 FIELDS name "Cross Cancer Institute" services "ultrasound,fluoroscopy,mri,mammography,physicaltherapy,tumourtriage" location "-113.5313 53.5177" OK > FT.ADD ft_providers grey-nuns-community-hospital 1.0 FIELDS name "Grey Nuns Community Hospital" services "respiratorytherapy,orthopedics,nucelarmedicine,labouranddelivery,fluoroscopy,intensivecare" location "-113.4283 53.4608" OK > FT.ADD ft_providers university-of-alberta-hospital 1.0 FIELDS name "University of Alberta Hospital" services "colonoscopy,intensivecare,nucelarmedicine,respiratorytherapy,gastroscopy" location "-113.5247 53.5205" OK > FT.ADD ft_providers misericordia-community-hospital 1.0 FIELDS name "Misericordia Community Hospital" services "orthopedics,geriatrics,footclinic,ultrasound,labouranddelivery" location "-113.6119 53.5207" OK
在搜索和查询中获得数据后,我们可以开始搜索设施信息。在搜索和查询中,我们使用一个名为 FT.SEARCH 的命令。第一个参数是要搜索的索引,第二个参数是查询。在搜索和查询中,你可以指定一个确定将返回什么结果的查询。查询可以非常简单,也可以非常复杂,但是与其他某些数据库中查询不同的是,查询绝不会执行任何管理或破坏性操作。
假设你想在上面使用的示例位置附近找到提供者,但是只能找到提供超声服务的提供者。在搜索和查询中,可以进行这样的查询
> FT.SEARCH ft_providers "@location:[-113.4967 53.5574 5 km] @services:{ultrasound}" 1) (integer) 2 2) "cross-cancer-institute" 3) 1) "name" 2) "Cross Cancer Institute" 3) "location" 4) "-113.5313 53.5177" 5) "services" 6) "ultrasound,fluoroscopy,mri,mammography,physicaltherapy,tumourtriage" 4) "royal-alex" 5) 1) "name" 2) "Royal Alex Hospital" 3) "location" 4) "-113.4967 53.5574" 5) "services" 6) "kidneyclinic,footclinic,gastroscopy,geriatrics,intensivecare,plasticsurgery,ultrasound"
在搜索和查询中,@符号表示“在特定字段中搜索”。查询的第一部分是对名为location的地理空间字段的搜索子句。你会注意到,方括号中的参数与你在GEORADIUS命令中看到的一样:经度后跟纬度,然后是搜索半径和单位。第二个@ 符号后跟字段名称services, 这意味着我们在每份文件的服务字段中进行搜索。花括号内是字段中必须包含的标签名称。在这种情况下,我们正在寻找包含标签ultrasound的文档。在位置和服务搜索子句之间有一个空格 - 在搜索和查询中,这是一个隐式的AND。
在构建 UI 时,你可以将各种用户输入合成到同一个查询中,以优化结果。下面着重介绍了这种方法可能如何运作
从应用程序的角度来看,UI 元素是字符串的表示形式,当它们更改时,它们会将你作为模板放入传递给FT.SEARCH的字符串中。SQL 查询中的字符串插值是有风险的(请参阅小Bobby Tables),这归结于 SQL 语言中的管理操作。相比之下,搜索和查询查询只能查找文档,不能执行管理操作,因此只需要简单的输入验证和健全性检查。
提高搜索复杂性,如果用户同时选中 ultrasound和geriatrics,你可以更改services子句以通过在放置在这里的两个标签之间插入竖线(|)来包含两者,如下所示:
> FT.SEARCH ft_providers "@location:[-113.4967 53.5574 5 km] @services:{ultrasound|geriatrics}" 1) (integer) 2 2) "royal-alex" 3) 1) "name" 2) "Royal Alex Hospital" 3) "location" 4) "-113.4967 53.5574" 5) "services" 6) "kidneyclinic,footclinic,gastroscopy,geriatrics,intensivecare,plasticsurgery,ultrasound" 4) "cross-cancer-institute" 5) 1) "name" 2) "Cross Cancer Institute" 3) "location" 4) "-113.5313 53.5177" 5) "services" 6) "ultrasound,fluoroscopy,mri,mammography,physicaltherapy,tumourtriage"
搜索和查询足以灵活地处理此类应用程序所需的任何其他功能。该类查询中,名称和名称前缀搜索、相似发音名称和街道名称等操作都是增量步骤。例如,您可以通过将数值字段纳入模式中添加一项出色的等待时间功能。搜索和查询是实时搜索引擎,它可以快速更新该值,因此尝试寻找最短等待时间的提供商的患者将始终获得最新结果。
Redis 可以帮助您使用几行代码构建简单的医疗保健提供商查找器,而搜索和查询可以填充您可能需要的所有功能,这样,患者就可以找到满足其需求的提供商。由于 Redis 和搜索和查询具有内置地理空间功能,因此您无需进行任何数学运算。搜索和查询为您提供丰富的查询功能,可以安全地接受患者输入,并且能够实时更新,这意味着在不向患者提供过时信息的情况下,您可以进行更改。