HarmonyOS学习路之开发篇—数据管理(融合搜索)

融合搜索概述

HarmonyOS融合搜索为开发者提供搜索引擎级的全文搜索能力,可支持应用内搜索和系统全局搜索,为用户提供更加准确、高效的搜索体验。

基本概念

  • 全文索引

    记录字或词的位置和次数等属性,建立的倒排索引。

  • 全文搜索

    通过全文索引进行匹配查找结果的一种搜索引擎技术。

  • 全局搜索

    可以在系统全局统一的入口进行的搜索行为。

  • 全局搜索应用

    HarmonyOS上提供全局搜索入口的应用,一般为桌面下拉框或悬浮搜索框。

  • 索引源应用

    通过融合搜索索引接口对其数据建立索引的应用。

  • 可搜索配置

    每个索引源应用应该提供一个包括应用包名、是否支持全局搜索等信息的可搜索实体,以便全局搜索应用发起搜索。

  • 群组

    经过认证的可信设备圈,可从账号模块获取群组ID。

  • 索引库

    一种搜索引擎的倒排索引库,包含多个索引文件的整个目录构成一个索引库。

  • 索引域

    索引数据的字段名,比如一张图片有文件名、存储路径、大小、拍摄时间等,文件名就是其中的一个索引域。

  • 索引属性

    描述索引域的信息,包括索引类型、是否为主键、是否存储、是否支持分词等。

运作机制

索引源应用通过融合搜索接口设置可搜索实体,并为其数据内容构建全文索引。全局搜索应用接收用户发起的搜索请求,遍历支持全局搜索的可搜索实体,解析用户输入并构造查询条件,最后通过融合搜索接口获取各应用搜索结果。

图1 融合搜索运作示意图

 

约束与限制

  • 构建索引或者发起搜索前,索引源应用必须先设置索引属性,并且必须有且仅有一个索引域设置为主键,且主键索引域不能分词,索引和搜索都会使用到索引属性。
  • 索引源应用的数据发生变动时,开发者应同步通过融合搜索索引接口更新索引,以保证索引和应用原始数据的一致性。
  • 批量创建、更新、删除索引时,应控制单次待索引内容大小,建议分批创建索引,防止内存溢出。
  • 分页搜索和分组搜索应控制每页返回结果数量,防止内存溢出。
  • 构建和搜索本机索引时,应该使用提供的SearchParameter.DEFAULT_GROUP作为群组ID,分布式索引使用通过账号模块获取的群组ID。
  • 搜索时需先创建搜索会话,并务必在搜索结束时关闭搜索会话,释放内存资源。
  • 使用融合搜索服务接口需要在“config.json”配置文件中添加“ohos.permission.ACCESS_SEARCH_SERVICE”权限。
  • 搜索时的SearchParamter.DEVICE_ID_LIST必须与创建索引时的deviceId一致。

融合搜索开发

场景介绍

索引源应用,一般为有持久化数据的应用,可以通过融合搜索接口为其应用数据建立索引,并配置全局搜索可搜索实体,帮助用户通过全局搜索应用查找本应用内的数据。应用本身提供搜索框时,也可直接在应用内部通过融合搜索接口实现全文搜索功能。

接口说明

HarmonyOS中的融合搜索为开发者提供以下几种能力,详见API参考。

表1 融合搜索接口功能介绍

类名

接口名

描述

SearchAbility

public List<IndexData> insert(String groupId, String bundleName, List<IndexData> indexDataList)

索引插入

public List<IndexData> update(String groupId, String bundleName, List<IndexData> indexDataList)

索引更新

public List<IndexData> delete(String groupId, String bundleName, List<IndexData> indexDataList)

索引删除

SearchSession

public int getSearchHitCount(String queryJsonStr)

搜索命中结果数量

public List<IndexData> search(String queryJsonStr, int start, int limit)

分页搜索

public List<Recommendation> groupSearch(String queryJsonStr, int groupLimit)

分组搜索

开发步骤

在config.json中添加permisssion权限。

// 添加在abilities同一目录层级
"reqPermissions": [{"name": "ohos.permission.ACCESS_SEARCH_SERVICE"}
]

实例化SearchAbility, 连接融合搜索服务。

SearchAbility searchAbility = new SearchAbility(context);
String bundleName = context.getBundleName();
CountDownLatch lock = new CountDownLatch(1);// 连接服务
searchAbility.connect(new ServiceConnectCallback() {@Overridepublic void onConnect() {lock.countDown();}@Overridepublic void onDisconnect() {}
});// 等待回调,最长等待时间可自定义。
try {lock.await(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {HiLog.error(LABEL, "await failed, %{public}s", e.getMessage());
}
if (searchAbility.hasConnected()) {// 连接成功
} else {// 连接失败,可重试。
}

设置索引属性。

// 构造自定义索引属性
List<IndexForm> indexFormList = new ArrayList<IndexForm>() { {add(new IndexForm("tag", IndexType.SORTED, false, true, false)); // 分词,同时支持排序、分组add(new IndexForm("bucket_id", IndexType.INTEGER, false, true, false)); // 支持排序和范围查询add(new IndexForm("latitude", IndexType.FLOAT, false, true, false)); // 支持范围搜索add(new IndexForm("longitude", IndexType.DOUBLE, false, true, false)); // 支持范围搜索add(new IndexForm("device_id", IndexType.NO_ANALYZED, false, true, false)); // 支持搜索
} };// 使用通用模板设置索引属性
int result = searchAbility.setIndexForm(bundleName, 1, indexFormList, IndexSchemaType.COMMON);
if (result == 1) {// 设置索引属性成功
} else {// 设置索引属性失败,可重试
}

插入索引。

// 构建索引数据
List<IndexData> indexDataList = new ArrayList<>();
for (int i = 0; i < 5; i++) {CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i) // identifier为主键        .setTitle("白云").setSubtitle("subtitle")        .setCategory("things")        .setDescription("is description")        .setName("name").setAlternateName("othername").setDateCreate(System.currentTimeMillis()).setKeywords("key").setPotentialAction("com.sample.search.TestAbility").setThumbnailUrl(FILE_PATH)        .setUrl(FILE_PATH).setReserved1(REVERSE_VALUE).setReserved2("reserved");commonItem.put("tag", "天空" + i);commonItem.put("bucket_id", i);commonItem.put("latitude", i / 5.0 * 180);commonItem.put("longitude", i / 5.0 * 360);commonItem.put("device_id", "localDeviceId");indexDataList.add(commonItem);
}// 插入索引
List<IndexData> failedList = searchAbility.insert(SearchParameter.DEFAULT_GROUP, bundleName, indexDataList);
// 失败的记录可以持久化,稍后重试。

构建查询。

// 构建查询
ZSONObject zsonObject = new ZSONObject();// SearchParameter.QUERY对应用户输入,建议搜索域分词。
// 这里假设用户输入是“天空”,要在"title", "tag"这两个域上发起搜索。
ZSONObject query = new ZSONObject();
query.put("天空", new ZSONArray(Arrays.asList(CommonItem.TITLE, "tag")));
zsonObject.put(SearchParameter.QUERY, query);// SearchParameter.FILTER_CONDITION对应的ZSONArray里可以添加搜索条件。
// 对于索引库里的一条索引,ZSONArray下的每个ZSONObject指定的条件都必须满足才会命中,ZSONObject里的条件组合满足其中一个,这个ZSONObject指定的条件即可满足。
ZSONArray filterCondition = new ZSONArray();
// 第一个条件,一个域上可能取多个值。
ZSONObject filter1 = new ZSONObject();
filter1.put("bucket_id", new ZSONArray(Arrays.asList(0, 1, 2))); // 一条索引在"bucket_id"的取值为0或1或2就能命中。
filter1.put(CommonItem.IDENTIFIER, new ZSONArray(Arrays.asList(0, 1))); // 或者在CommonItem.IDENTIFIER的取值为0或者1也可以命中。
filterCondition.add(filter1);ZSONObject filter2 = new ZSONObject();
filter2.put("tag", new ZSONArray(Arrays.asList("白云")));
filter2.put(CommonItem.TITLE, new ZSONArray(Arrays.asList("白云"))); // 一条索引只要在"tag"或者CommonItem.TITLE上命中"白云"就能命中。
filterCondition.add(filter2);
zsonObject.put(SearchParameter.FILTER_CONDITION, filterCondition); // 一条索引要同时满足第一和第二个条件才能命中。// SearchParameter.DEVICE_ID_LIST对应设备ID,匹配指定设备ID的索引才会命中。
ZSONObject deviceId = new ZSONObject();
deviceId.put("device_id", new ZSONArray(Arrays.asList("localDeviceId"))); // 指定本机设备。
zsonObject.put(SearchParameter.DEVICE_ID_LIST, deviceId);// 可以在支持范围搜索的索引域上发起范围搜索,一条索引在指定域的值落在对应的指定范围才会命中。
ZSONObject latitudeObject = new ZSONObject();
latitudeObject.put(SearchParameter.LOWER, -40.0f);
latitudeObject.put(SearchParameter.UPPER, 40.0f);
zsonObject.put("latitude", latitudeObject); // 纬度必须在[-40.0f, 40.0f]ZSONObject longitudeObject = new ZSONObject();
longitudeObject.put(SearchParameter.LOWER, -90.0);
longitudeObject.put(SearchParameter.UPPER, 90.0);
zsonObject.put("longitude", longitudeObject); // 经度必须在[-90.0, 90.0]// SearchParameter.ORDER_BY对应搜索结果的排序,排序字段通过SearchParameter.ASC和SearchParameter.DESC指定搜索结果在这个字段上按照升序、降序排序。
// 这里填充字段的顺序是重要的,比如这里两个索引之间会先在CommonItem.CATEGORY字段上升序排序,只有在CommonItem.CATEGORY上相同时,才会继续在"tag"上降序排序,以此类推。
ZSONObject order = new ZSONObject();
order.put(CommonItem.CATEGORY, SearchParameter.ASC);
order.put("tag", SearchParameter.DESC);
zsonObject.put(SearchParameter.ORDER_BY, order);// SearchParameter.GROUP_FIELD_LIST对应分组搜索的域,调用groupSearch接口需要指定。
zsonObject.put(SearchParameter.GROUP_FIELD_LIST, new ZSONArray(Arrays.asList("tag", CommonItem.CATEGORY)));// 得到查询字符串。
String queryZsonStr = zsonObject.toString();// 构建的json字符串如下:
/**
{"SearchParameter.QUERY": {"天空": ["title","tag"]},"SearchParameter.FILTER_CONDITION": [{"bucket_id": [0,1,2],"identifier": [0,1]},{"tag": ["白云"],"title": ["白云"]}],"SearchParameter.DEVICE_ID_LIST": {"device_id": ["localDeviceId"]},"latitude": {"SearchParameter.LOWER": -40.0,"SearchParameter.UPPER": 40.0},"longitude": {"SearchParameter.LOWER": -90.0,"SearchParameter.UPPER": 90.0},"SearchParameter.ORDER_BY": {"category": "ASC","tag": "DESC"},"SearchParameter.GROUP_FIELD_LIST": ["tag","category"]
}
**/

开始搜索会话,发起搜索。

// 开始搜索会话
SearchSession searchSession = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, bundleName);
if (searchSession == null) {return;
}
try {int hit = searchSession.getSearchHitCount(queryJsonStr); // 获取总命中数int batch = 50; // 每页最多返回50个结果for (int i = 0; i < hit; i += batch) {List<IndexData> searchResult = searchSession.search(queryJsonStr, i, batch);// 处理IndexData}int groupLimit = 10; // 每个分组域上最多返回10个分组结果List<Recommendation> recommendationResult = searchSession.groupSearch(queryJsonStr, groupLimit);// 处理Recommendation
} finally {// 结束搜索,释放资源searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, bundleName, searchSession);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/14773.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务之服务器缓存

Informal Essay By English In the difficult employment situation, we need to set a good goal and then do our own thing 参考书籍&#xff1a;“凤凰架构” 进程缓存&#xff08;Cache&#xff09; 缓存在分布式系统是可选&#xff0c;在使用缓存之前需要确认你的系统…

Redis - 附近商铺、用户签到、UV统计

文章目录 附近商铺、用户签到、UV统计一、附近商铺1.1 GEO数据结构1.2 导入店铺数据到GEO1.3 实现附近商户功能 二、用户签到2.1 BitMap2.2 签到功能2.3 统计连续签到2.3.1 分析2.3.2 代码实现 三、UV统计3.1 HyperLogLog用法3.2 测试百万数据的统计 附近商铺、用户签到、UV统计…

系统架构设计师-软件工程(3)

一、软件系统建模 1、结构化建模方法 结构化建模方法是以过程为中心的技术&#xff0c;可用于分析一个现有系统以及定义新系统的业务需求。结构化建模方法所绘制的模型称为数据流图&#xff08;DFD&#xff09;。对于流程较为稳定的系统可考虑结构化建模方法。 2、信息工程建模…

简单详细的MySQL数据库结构及yum和通用二进制安装mysql的方法

目录 mysql体系结构mysql的安装方法一&#xff0c;yum安装1&#xff0c;首先下载一个网络源仓库&#xff1a;2&#xff0c;然后安装 mysql-community-server3&#xff0c;启动mysqld 服务4&#xff0c;然后登录数据库5&#xff0c;初次登录要设置密码&#xff0c;而且不能太简单…

【ROS】TF2坐标转换及实战示例

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法…感兴趣就关注我吧&#xff01;你定不会失望。 文章目录 0.ROS中的坐标转换消息包0.1 geometry_msgs/TransformStamped0.2 geometry_msgs/PointStamped1.静态坐标转换1.1导入所需功能包1.2发布方实现1.3 …

【InnoDB 存储引擎】InnoDB 存储引擎的行格式,有 Compact、Redundant、Dynamic 等行格式还有它们配套实验(实验篇)

文章目录 1 InnoDB 行记录格式&#xff08;实验&#xff09;1.1 Compact 行格式实验1.1.1 实验步骤1.1.2 分析捞出来的数据1.1.3 疑问 1.2 Redundant 行格式实验1.2.1 实验步骤1.2.2 分析捞出来的数据 1.3 CHAR 列类型的存储1.3.1 实验步骤1.3.2 分析捞出来的数据 2 参考资料 1…

pnpm装包报错Run “pnpm install“ to recreate the modules directory.

一、先看报错 执行 pnpm install 装包报错 报错信息 ERR_PNPM_PUBLIC_HOIST_PATTERN_DIFF  This modules directory was created using a different public-hoist-pattern value. Run "pnpm install" to recreate the modules directory.二、解决方法 在项目根目录中…

【Zabbix 监控设置】

目录 一、添加 zbx-agent01 客户端主机1、服务端和客户端都配置时间同步2、服务端和客户端都设置 hosts 解析3、设置 zabbix 的下载源&#xff0c;安装 zabbix-agent24、修改 agent2 配置文件5、启动 zabbix-agent26、在服务端验证 zabbix-agent2 的连通性1、常用的键值 7、在 …

基于云原生网关的全链路灰度实践

作者&#xff1a; 倪海峰&#xff08;海迩&#xff09; 前言 随着企业规模的不断扩大&#xff0c;传统单体应用已很难进一步支持业务的发展&#xff0c;业务的迭代速度已经难以满足业务的增长&#xff0c;此时企业会对应用系统做微服务化的改造&#xff0c;降低业务的耦合度&…

Opencv图片样本预处理

前因 最近想学学&#xff0c;OPENCV识别物体&#xff0c;但是处理图片正样本时过于繁琐&#xff0c; 遂自己开发了工具&#xff0c;来处理样本图片&#xff0c;基于QT&#xff0c;文末附下载链接 程序 功能 一共有两个功能&#xff0c;一个是处理负样本&#xff0c;一个处理…

Spring Boot源码解读与原理分析(一):项目启动流程(上)——@SpringBootApplication

文章目录 〇、准备工作一、SpringBootApplication.java源码解析1.源码2.自定义注解3.组合注解4.注解ComponentScan过滤器 5.注解SpringBootConfigurationConfiguration 6.注解EnableAutoConfiguration 本文章是Spring Boot源码解读与原理分析系列博客的第一篇&#xff0c;将会介…

【js小案例】视频倍数播放、计算机、待办事项管理

视频倍数播放示例图&#xff1a; 视频倍数播放代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>控制视频播放速度</title> </head> <body><video id"myVideo" width&quo…