赞
踩
HarmonyOS融合搜索为开发者提供搜索引擎级的全文搜索能力,可支持应用内搜索和系统全局搜索,为用户提供更加准确、高效的搜索体验。
记录字或词的位置和次数等属性,建立的倒排索引。
通过全文索引进行匹配查找结果的一种搜索引擎技术。
可以在系统全局统一的入口进行的搜索行为。
HarmonyOS上提供全局搜索入口的应用,一般为桌面下拉框或悬浮搜索框。
通过融合搜索索引接口对其数据建立索引的应用。
每个索引源应用应该提供一个包括应用包名、是否支持全局搜索等信息的可搜索实体,以便全局搜索应用发起搜索。
经过认证的可信设备圈,可从账号模块获取群组ID。
一种搜索引擎的倒排索引库,包含多个索引文件的整个目录构成一个索引库。
索引数据的字段名,比如一张图片有文件名、存储路径、大小、拍摄时间等,文件名就是其中的一个索引域。
描述索引域的信息,包括索引类型、是否为主键、是否存储、是否支持分词等。
索引源应用通过融合搜索接口设置可搜索实体,并为其数据内容构建全文索引。全局搜索应用接收用户发起的搜索请求,遍历支持全局搜索的可搜索实体,解析用户输入并构造查询条件,最后通过融合搜索接口获取各应用搜索结果。
图1 融合搜索运作示意图
索引源应用,一般为有持久化数据的应用,可以通过融合搜索接口为其应用数据建立索引,并配置全局搜索可搜索实体,帮助用户通过全局搜索应用查找本应用内的数据。应用本身提供搜索框时,也可直接在应用内部通过融合搜索接口实现全文搜索功能。
HarmonyOS中的融合搜索为开发者提供以下几种能力,详见API参考。
类名 | 接口名 | 描述 |
---|---|---|
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() {
- @Override
- public void onConnect() {
- lock.countDown();
- }
-
- @Override
- public 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);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。