鴻蒙OS 融合搜索開發(fā)指導(dǎo)

2020-09-18 17:51 更新

場景介紹

索引源應(yīng)用,一般為有持久化數(shù)據(jù)的應(yīng)用,可以通過融合搜索接口為其應(yīng)用數(shù)據(jù)建立索引,并配置全局搜索可搜索實體,幫助用戶通過全局搜索應(yīng)用查找本應(yīng)用內(nèi)的數(shù)據(jù)。應(yīng)用本身也提供搜索框時,也可直接在應(yīng)用內(nèi)部通過融合搜索接口實現(xiàn)全文搜索功能。

接口說明

HarmonyOS 中的融合搜索為開發(fā)者提供以下幾種能力,詳見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) 搜索命中結(jié)果數(shù)量
public List<IndexData> search(String queryJsonStr, int start, int limit) 分頁搜索
public List<Recommendation> groupSearch(String queryJsonStr, int groupLimit) 分組搜索

開發(fā)步驟

實例化 SearchAbility,連接融合搜索服務(wù)。

  1. SearchAbility searchAbility = new SearchAbility(context);
  2. CountDownLatch lock = new CountDownLatch(1);
  3. // 連接服務(wù)
  4. searchAbility.connect(new ServiceConnectCallback() {
  5. @Override
  6. public void onConnect() {
  7. lock.countDown();
  8. }
  9. @Override
  10. public void onDisconnect() {
  11. }
  12. });
  13. // 等待回調(diào),最長等待時間可自定義
  14. lock.await(3000, TimeUnit.MILLISECONDS);
  15. // 連接失敗可重試

設(shè)置索引屬性。

  1. // 構(gòu)造索引屬性
  2. List<IndexForm> indexFormList = new ArrayList<>();
  3. IndexForm primaryKey = new IndexForm("id", IndexType.NO_ANALYZED, true, true, false); // 主鍵,不分詞
  4. indexFormList.add(primaryKey);
  5. IndexForm title = new IndexForm("title", IndexType.ANALYZED, false, true, true); // 分詞
  6. indexFormList.add(title);
  7. IndexForm tagType = new IndexForm("tag_type", IndexType.SORTED, false, true, false); // 分詞,同時支持排序、分組
  8. indexFormList.add(tagType);
  9. IndexForm ocrText = new IndexForm("ocr_text", IndexType.SORTED_NO_ANALYZED, false, true, false); // 支持排序、分組,不分詞,所以也支持范圍搜索
  10. indexFormList.add(ocrText);
  11. IndexForm dateTaken = new IndexForm("datetaken", IndexType.LONG, false, true, false); // 支持排序和范圍查詢
  12. indexFormList.add(dateTaken);
  13. IndexForm bucketId = new IndexForm("bucket_id", IndexType.INTEGER, false, true, false); // 支持排序和范圍查詢
  14. indexFormList.add(bucketId);
  15. IndexForm latitude = new IndexForm("latitude", IndexType.FLOAT, false, true, false); // 支持范圍搜索
  16. indexFormList.add(latitude);
  17. IndexForm longitude = new IndexForm("longitude", IndexType.DOUBLE, false, true, false); // 支持范圍搜索
  18. indexFormList.add(longitude);
  19. // 設(shè)置索引屬性
  20. int result = searchAbility.setIndexForm(bundleName, 1, indexFormList);
  21. // 設(shè)置失敗可重試

插入索引。

  1. // 構(gòu)建索引數(shù)據(jù)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_type", "tag_type" + i); indexData.put("ocr_text", "ocr_text" + i); indexData.put("dat// 構(gòu)建索引數(shù)據(jù)
  2. List<IndexData> indexDataList = new ArrayList<>();
  3. for (int i = 0; i < 5; i++) {
  4. IndexData indexData = new IndexData();
  5. indexData.put("id", "id" + i);
  6. indexData.put("title", "title" + i);
  7. indexData.put("tag_type", "tag_type" + i);
  8. indexData.put("ocr_text", "ocr_text" + i);
  9. indexData.put("datetaken", System.currentTimeMillis());
  10. indexData.put("bucket_id", i);
  11. indexData.put("latitude", i / 5.0 * 180);
  12. indexData.put("longitude", i / 5.0 * 360);
  13. indexDataList.add(indexData);
  14. }
  15. // 插入索引
  16. List<IndexData> failedList = searchAbility.insert(SearchParameter.DEFAULT_GROUP, bundleName, indexDataList);
  17. // 失敗的記錄可以持久化,稍后重試etaken", 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);// 失敗的記錄可以持久化,稍后重試

構(gòu)建查詢。

  1. // 構(gòu)建查詢
  2. JSONObject jsonObject = new JSONObject();
  3. // SearchParameter.QUERY對應(yīng)用戶輸入,搜索域應(yīng)該都是分詞的
  4. // 這里假設(shè)用戶輸入是“天空”,要在"title", "tag_type"這兩個域上發(fā)起搜索
  5. JSONObject query = new JSONObject();
  6. query.put("天空", new JSONArray(Arrays.asList("title", "tag_type")));
  7. jsonObject.put(SearchParameter.QUERY, query);
  8. // SearchParameter.FILTER_CONDITION對應(yīng)的JSONArray里可以添加搜索條件
  9. // 對于索引庫里的一條索引,JSONArray下的每個JSONObject指定的條件都必須滿足才會命中,JSONObject里的條件組合滿足其中一個,這個JSONObject指定的條件即可滿足
  10. JSONArray filterCondition = new JSONArray();
  11. // 第一個條件,一個域上可能取多個值
  12. JSONObject filter1 = new JSONObject();
  13. filter1.put("bucket_id", new JSONArray(Arrays.asList(0, 1, 2))); // 一條索引在"bucket_id"的取值為0或1或2就能命中
  14. filter1.put("id", new JSONArray(Arrays.asList(0, 1))); // 或者在"id"的取值為0或者1也可以命中
  15. filterCondition.put(filter1);
  16. // 第二個條件,一個值可能在多個域上命中
  17. JSONObject filter2 = new JSONObject();
  18. filter2.put("tag_type", new JSONArray(Arrays.asList("白云")));
  19. filter2.put("ocr_text", new JSONArray(Arrays.asList("白云"))); // 一條索引只要在"tag_type"或者"ocr_text"上命中"白云"就能命中
  20. filterCondition.put(filter2);
  21. jsonObject.put(SearchParameter.FILTER_CONDITION, filterCondition); // 一條索引要同時滿足第一和第二個條件才能命中
  22. // SearchParameter.DEVICE_ID_LIST對應(yīng)設(shè)備ID,匹配指定設(shè)備ID的索引才會命中
  23. JSONObject deviceId = new JSONObject();
  24. deviceId.put("device_id", new JSONArray(Arrays.asList("localDeviceId")));
  25. jsonObject.put(SearchParameter.DEVICE_ID_LIST, deviceId);
  26. // 可以在支持范圍搜索的索引域上發(fā)起范圍搜索,一條索引在指定域的值都落在對應(yīng)的指定范圍才會命中
  27. JSONObject latitude = new JSONObject();
  28. latitude.put(SearchParameter.LOWER, -40.0f); // inclusive
  29. latitude.put(SearchParameter.UPPER, 40.0.f); // inclusive
  30. jsonObject.put("latitude", latitude); // 緯度必須在[-40.0f, 40.0f]
  31. JSONObject longitude new JSONObject();
  32. longitude.put(SearchParameter.LOWER, -90.0); // inclusive
  33. longitude.put(SearchParameter.UPPER, 90.0); // inclusive
  34. jsonObject.put("longitude", longitude); // 經(jīng)度必須在[-90.0, 90.0]
  35. // SearchParameter.ORDER_BY對應(yīng)搜索結(jié)果的排序,排序字段通過SearchParameter.ASC和SearchParameter.DESC
  36. // 指定搜索結(jié)果在這個字段上按照升序、降序排序,這里填充字段的順序是重要的,比如這里兩個索引之間會先在"id"
  37. // 字段上升序排序,只有在"id"上相同時,才會繼續(xù)在"datetaken"上降序排序,以此類推
  38. JSONObject order = new JSONObject();
  39. order.put("id", SearchParameter.ASC);
  40. order.put("title", SearchParameter.ASC);
  41. order.put("datetaken", SearchParameter.DESC);
  42. jsonObject.put(SearchParameter.ORDER_BY, order);
  43. // SearchParameter.GROUP_FIELD_LIST對應(yīng)的群組搜索的域,調(diào)用gruopSearch接口需要指定
  44. jsonObject.put(SearchParameter.GROUP_FIELD_LIST, new JSONArray(Arrays.asList("tag_type", "ocr_text")));
  45. // 得到查詢字符串
  46. String queryJsonStr = jsonObject.toString();
  47. // 構(gòu)建的json字符串如下:
  48. /**
  49. {
  50. "SearchParameter.QUERY": {
  51. "天空": [
  52. "title",
  53. "tag_type"
  54. ]
  55. },
  56. "SearchParameter.FILTER_CONDITION": [
  57. {
  58. "bucket_id": [
  59. 0,
  60. 1,
  61. 2
  62. ],
  63. "id": [
  64. 0,
  65. 1
  66. ]
  67. },
  68. {
  69. "tag_type": [
  70. "白云"
  71. ],
  72. "ocr_text": [
  73. "白云"
  74. ]
  75. }
  76. ],
  77. "SearchParameter.DEVICE_ID_LIST": {
  78. "device_id": [
  79. "localDeviceId"
  80. ]
  81. },
  82. "latitude": {
  83. "SearchParameter.LOWER": -40.0,
  84. "SearchParameter.UPPER": 40.0
  85. },
  86. "longitude": {
  87. "SearchParameter.LOWER": -90.0,
  88. "SearchParameter.UPPER": 90.0
  89. },
  90. "SearchParameter.ORDER_BY": {
  91. "id": "ASC",
  92. "title": "ASC",
  93. "datetaken": "DESC"
  94. },
  95. "SearchParameter.GROUP_FIELD_LIST": [
  96. "tag_type",
  97. "ocr_text"
  98. ]
  99. }
  100. **/

開始搜索會話,發(fā)起搜索。

  1. // 開始搜索會話
  2. SearchSession searchSession = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, bundleName);
  3. if (searchSession == null) {
  4. return;
  5. }
  6. try {
  7. int hit = searchSession.getSearchHitCount(queryJsonStr); // 獲取總命中數(shù)
  8. int batch = 50; // 每頁最多返回50個結(jié)果
  9. for (int i = 0; i < hit; i += batch) {
  10. List<IndexData> result = searchSession.search(queryJsonStr, i, batch);
  11. ...
  12. // 處理IndexData
  13. }
  14. int groupLimit = 10; // 每個分組域上最多返回10個分組結(jié)果
  15. List<Recommendation> result = searchSession.groupSearch(queryJsonStr, groupLimit);
  16. // 處理Recommendation
  17. for (Recommendation recommendation : result) {
  18. HiLog.info(LABEL, "field: %{public}s, value: %{public}s, count: %{public}d", recommedation.getField(), recommendation.getValue(), recommendation.getCount());
  19. }
  20. } finally {
  21. // 釋放資源
  22. searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, bundleName, searchSession);
  23. }
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號