融合搜索:开发指导
目录场景介绍接口说明开发步骤场景介绍索引源应用,一般为有持久化数据的应用,可以通过融合搜索接口为其应用数据建立索引,并配置全局搜索可搜索实体,帮助用户通过全局搜索应用查找本应用内的数据。应用本身提供搜索框时,也可直接在应用内部通过融合搜索接口实现全文搜索功能。接口说明HarmonyOS中的融合搜索为开发者提供以下几种能力,详见API参考。表1融合搜索接口功能介绍类名接口名描述Searc.
目录
场景介绍
索引源应用,一般为有持久化数据的应用,可以通过融合搜索接口为其应用数据建立索引,并配置全局搜索可搜索实体,帮助用户通过全局搜索应用查找本应用内的数据。应用本身提供搜索框时,也可直接在应用内部通过融合搜索接口实现全文搜索功能。
接口说明
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) |
分组搜索 |
开发步骤
- 实例化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()); } // 连接失败可重试。
- 设置索引属性。
// 构造索引属性 List<IndexForm> indexFormList = new ArrayList<IndexForm>() { { add(new IndexForm("id", IndexType.NO_ANALYZED, true, true, false)); // 主键,不分词 add(new IndexForm("title", IndexType.ANALYZED, false, true, true)); // 分词 add(new IndexForm("tag", IndexType.SORTED, false, true, false)); // 分词,同时支持排序、分组 add(new IndexForm("ocr_text", IndexType.SORTED_NO_ANALYZED, false, true, false)); // 支持排序、分组,不分词,所以也支持范围搜索 add(new IndexForm("datetaken", IndexType.LONG, 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)); // 支持范围搜索 } }; // 设置索引属性 int result = searchAbility.setIndexForm(bundleName, 1, indexFormList); // 设置失败可重试
- 插入索引。
// 构建索引数据 List<IndexData> indexDataList = new ArrayList<>(); for (int i = 0; i < 5; i++) { IndexData indexData = new IndexData(); indexData.put("id", "id" + i); indexData.put("title", "title" + i); indexData.put("tag", "tag" + i); indexData.put("ocr_text", "ocr_text" + i); indexData.put("datetaken", System.currentTimeMillis()); indexData.put("bucket_id", i); indexData.put("latitude", i / 5.0 * 180); indexData.put("longitude", i / 5.0 * 360); indexDataList.add(indexData); } // 插入索引 List<IndexData> failedList = searchAbility.insert(SearchParameter.DEFAULT_GROUP, bundleName, indexDataList); // 失败的记录可以持久化,稍后重试。
- 构建查询。
// 构建查询 JSONObject jsonObject = new JSONObject(); // SearchParameter.QUERY对应用户输入,建议搜索域分词。 // 这里假设用户输入是“天空”,要在"title", "tag"这两个域上发起搜索。 JSONObject query = new JSONObject(); query.put("天空", new JSONArray(Arrays.asList("title", "tag"))); jsonObject.put(SearchParameter.QUERY, query); // SearchParameter.FILTER_CONDITION对应的JSONArray里可以添加搜索条件。 // 对于索引库里的一条索引,JSONArray下的每个JSONObject指定的条件都必须满足才会命中,JSONObject里的条件组合满足其中一个,这个JSONObject指定的条件即可满足。 JSONArray filterCondition = new JSONArray(); // 第一个条件,一个域上可能取多个值。 JSONObject filter1 = new JSONObject(); filter1.put("bucket_id", new JSONArray(Arrays.asList(0, 1, 2))); // 一条索引在"bucket_id"的取值为0或1或2就能命中。 filter1.put("id", new JSONArray(Arrays.asList(0, 1))); // 或者在"id"的取值为0或者1也可以命中。 filterCondition.put(filter1); JSONObject filter2 = new JSONObject(); filter2.put("tag", new JSONArray(Arrays.asList("白云"))); filter2.put("ocr_text", new JSONArray(Arrays.asList("白云"))); // 一条索引只要在"tag"或者"ocr_text"上命中"白云"就能命中。 filterCondition.put(filter2); jsonObject.put(SearchParameter.FILTER_CONDITION, filterCondition); // 一条索引要同时满足第一和第二个条件才能命中。 // SearchParameter.DEVICE_ID_LIST对应设备ID,匹配指定设备ID的索引才会命中。 JSONObject deviceId = new JSONObject(); deviceId.put("device_id", new JSONArray(Arrays.asList("localDeviceId"))); // 指定本机设备。 jsonObject.put(SearchParameter.DEVICE_ID_LIST, deviceId); // 可以在支持范围搜索的索引域上发起范围搜索,一条索引在指定域的值落在对应的指定范围才会命中。 JSONObject latitudeObject = new JSONObject(); latitudeObject.put(SearchParameter.LOWER, -40.0f); latitudeObject.put(SearchParameter.UPPER, 40.0f); jsonObject.put("latitude", latitudeObject); // 纬度必须在[-40.0f, 40.0f] JSONObject longitudeObject = new JSONObject(); longitudeObject.put(SearchParameter.LOWER, -90.0); longitudeObject.put(SearchParameter.UPPER, 90.0); jsonObject.put("longitude", longitudeObject); // 经度必须在[-90.0, 90.0] // SearchParameter.ORDER_BY对应搜索结果的排序,排序字段通过SearchParameter.ASC和SearchParameter.DESC指定搜索结果在这个字段上按照升序、降序排序。 // 这里填充字段的顺序是重要的,比如这里两个索引之间会先在"id"字段上升序排序,只有在"id"上相同时,才会继续在"datetaken"上降序排序,以此类推。 JSONObject order = new JSONObject(); order.put("id", SearchParameter.ASC); order.put("datetaken", SearchParameter.DESC); jsonObject.put(SearchParameter.ORDER_BY, order); // SearchParameter.GROUP_FIELD_LIST对应分组搜索的域,调用groupSearch接口需要指定。 jsonObject.put(SearchParameter.GROUP_FIELD_LIST, new JSONArray(Arrays.asList("tag", "ocr_text"))); // 得到查询字符串。 String queryJsonStr = jsonObject.toString(); // 构建的json字符串如下: /** { "SearchParameter.QUERY": { "天空": [ "title", "tag" ] }, "SearchParameter.FILTER_CONDITION": [ { "bucket_id": [ 0, 1, 2 ], "id": [ 0, 1 ] }, { "tag": [ "白云" ], "ocr_text": [ "白云" ] } ], "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": { "id": "ASC", "datetaken": "DESC" }, "SearchParameter.GROUP_FIELD_LIST": [ "tag", "ocr_text" ] } **/
- 开始搜索会话,发起搜索。
// 开始搜索会话 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); }
更多推荐
所有评论(0)