HarmonyOS-鸿蒙app开发 —基于java_数据管理_融合搜索开发指导

HarmonyOS-鸿蒙app开发 —基于java_数据管理_融合搜索开发指导

场景介绍

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

接口说明

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() {

@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);

}

🚀 如未找到文章请搜索栏搜素 | Ctrl+D收藏本站 | 联系邮箱:15810050733@qq.com