搜索有多复杂?





0/5 (0投票)
Cloudant 分布式数据库即服务 (DBaaS) 的设计旨在通过集成 Apache Lucene 搜索库来帮助您解决索引和搜索问题。
引言
搜索有多复杂?
通常我们在早期开发阶段不会问这个问题,这就是为什么有些项目的架构与快速高效搜索的需求不符。
在这些“通常”情况下,项目进入重构阶段,并与产品负责人不断讨论重建或重新设计项目以实现更快更高效搜索所需的时间和资源。
Cloudant 分布式数据库即服务 (DBaaS) 的设计旨在通过集成 Apache Lucene 搜索库来帮助您解决索引和搜索问题。
您从中获得的好处是,您的 NoSQL 数据库内置了专为 JSON 格式数据创建的索引。此外,索引计算和重新计算算法旨在分布式云环境中针对数据块高效运行。而且您无需编写任何代码或配置即可使用此功能。
简而言之
在设计文档中定义的搜索索引允许使用 Lucene 查询解析器语法 查询数据库。搜索索引由索引函数定义,类似于 MapReduce 视图中的映射函数。索引函数决定要索引和存储在索引中的数据。(摘自 https://docs.cloudant.com/search.html)
上面的引述很好地描述了 Cloudant 搜索引擎,但真正理解它的最好方法是举一个例子。因此,我们将以 Cloudant 为例,构建一个物联网解决方案,用于存储传感器数据和查询信息进行监控。
背景
什么是 Apache Lucene?
1999 年,Doug Cutting 发布了 Lucene 的第一个版本。2001 年,该项目加入了 Apache 软件基金会 Jakarta 系列的开源产品。此后,许多相关项目从 Lucene 分支出来。目前,这个开源搜索库是最流行的 JSON 文档处理库。
分布式数据库可以跨多个机架、数据中心甚至不同的云提供商进行扩展。Cloudant 中的 Apache Lucene 实现旨在让您在不损失效率和速度的情况下获得扩展的好处。
使用 RESTful API 或设计文档 Web UI,您可以定义索引,这些索引会立即构建并准备好使用。正如我们在之前的帖子中提到的,当关键操作发生时(例如创建、更新或删除),所有索引都会增量更新,包括 Lucene 索引。
Lucene 查询解析器语法
索引定义方式和查询语法的结合允许您对数据库中的任何 JSON 字段执行数字、日期、文本、布尔和地理空间查询。
以下是一些搜索语法的功能
- 排名搜索 - 不同的结果排序方式
- 强大的查询类型 - 通配符、正则表达式、模糊、近似、范围等
- 特定语言分析器 - 选择一种语言来识别文本中的术语
- 分面搜索和过滤
- 书签
使用代码
传感器模拟器
我们将重用之前帖子中的代码结构,扩展交付给 Cloudant DBaaS 的 JSON,使其包含更多内容。我们增强的传感器将像以前一样发送温度和湿度,但现在它们将包括设备 ID、地理位置、用户消息和错误消息。数据将直接流入 Cloudant DB。
这并不是物联网解决方案的常见架构设计,因为架构师更倾向于设计一个中间服务来提供安全和版本控制。使用 Cloudant,我们可以使用 Cloudant DBaaS 提供的 API 密钥级别的安全性,直接从设备向数据库发送数据。由于数据库是非关系型的,我们可以将不同的 JSON 版本集成到同一个数据库中,并由相同(或版本升级的)索引进行处理。
因此,我们有一个看起来像这样的 Sensor 类
public class Sensor
{
public string _id;
public string recordtitle;
public string record;
public string origtime;
public int displacement;
public int temp;
public int hmdt;
public long modified;
public string tags;
public string city;
public double lat;
public double lon;
public string deviceId;
public string userMessage;
public string errorMessage;
}
传感器数据生成方法预定义了设备 ID、城市和地理位置的几种组合,以及几种错误消息和用户消息。
构建搜索索引
多参数索引
使用设计文档 UI,我们将为我们查询的六个字段创建一个新的搜索索引
此搜索索引结合了我们每个记录中六个字段的六个搜索索引。这将允许我们执行复杂的查询,请求与这些字段相关的记录。例如
- 我们可以请求城市中的用户消息;
- 我们可以查询地理位置范围内的用户消息;
- 我们可以请求某个城市在某个时间段内的传感器数据
- 等等。
下面的代码为关键属性生成命名索引
function (doc) {
index("deviceId", doc.deviceId);
if (doc.origtime) {
index("time", doc.origtime, { "store" : true });
}
if (doc.lat && doc.lon) {
index("lat", doc.lat, { "store" : true });
index("lon", doc.lon, { "store" : true });
index("city", doc.city, { "store" : true });
}
if (doc.userMessage && doc.userMessage.length !== 0) {
index("userMessage", doc.userMessage, { "store" : true });
}
}
请注意,有些索引是带参数声明的
- “store”设置为 true 表示搜索引警需要保留该值并在请求时返回
- “facet”设置为 true 表示搜索引警需要计算不同值的重复次数
生成的搜索索引可以从 UI 中测试
分面搜索
为了方便 REST 访问,我们将为分面索引创建三个单独的搜索索引。我们在此处访问的字段是城市、传感器记录名称和错误消息(因为错误消息是有限的错误代码范围)。
最后我们将得到这种类型的设计文档
每个搜索索引方法都有这些代码
facetErrors
function (doc) {
if (doc.errorMessage && doc.errorMessage.length !== 0) {
index("errors", doc.errorMessage, { "facet":true });
}
}
facetCity
function (doc) {
if (doc.city) {
index("city", doc.city, { "store" : true, "facet" : true });
}
}
facetRecords
function (doc) {
if (doc.recordtitle) {
index("record", doc.recordtitle, { "store" : true, "facet" : true });
}
}
Azure Web App 可视化
对于这个演示,我们将为 Azure 云网站构建最简单的解决方案。
这就是我们从一个空模板开始的原因。
对 web.config 进行几项更改 - 添加应用程序设置并启用默认文档
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="username" value="[username]" />
<add key="password" value="[password]" />
</appSettings>
...
<system.webServer>
<defaultDocument enabled="true" />
...
</system.webServer>
</configuration>
安装一个 nuget 库(Cloudant DB 的 REST API 调用所需)
添加一个静态助手类来处理 Cloudant 搜索索引 - 在 GitHub 上的代码中查看。从 Cloudant 请求数据的三个方法中的关键行是指定过滤器的行。
获取分面搜索
request.AddQueryParameter("q", "*:*");
request.AddQueryParameter("counts", "[\""+counter+"\"]"); //
request.AddQueryParameter("limit", "0");
此类型请求中发送了三个参数
- 主过滤器的查询 - 在本例中为 *:*,因为我们想要计算所有已索引的记录
- 搜索索引名称的“counts”数组 - 在本例中,我们将分别请求“errors”、“city”和“records”
- “limit”参数用于限制返回的搜索结果 - 在本例中,我只需要计数,因此 limit 为零(不返回任何记录)
获取地理位置搜索
request.AddQueryParameter("q", "*:*");
request.AddQueryParameter("sort", "\"<distance,lon,lat," + lon + "," + lat + ",km>\"");
request.AddQueryParameter("limit", "5");
在这里我请求按距离给定纬度和经度排序的前五条记录。
获取文本搜索
request.AddQueryParameter("q", "userMessage:" + text + "*");
request.AddQueryParameter("limit", "10");
最后一个是简单搜索,请求的文本用通配符扩展,结果限制为 10 条记录。
Index.html
一个名为默认名称(为了成为默认打开的页面而命名为 Index.html)的简单 HTML 页面加载了 jQuery 和 Google 地图的 JavaScript。结果视图显示了分面计数和地图上的图钉
文本搜索显示了不同类型的图钉,带有弹出窗口显示用户消息文本。
关注点
此演示并未涵盖使用 Cloudant 搜索的所有方式,但它为我们提供了关于 Cloudant 搜索功能的一些知识 - 如何组合索引以及如何查询它们。在帖子中,我们构建了一个简单的基于 Azure 云的 Web 应用程序,该应用程序使用 Cloudnat DBaaS 进行存储和数据处理。我们还为物联网解决方案使用了不同的架构,并实现了更简单、更易于使用和维护的实现。