赞
踩
类名 | 接口名 | 描述 |
---|---|---|
SearchAbility | public List insert(String groupId, String bundleName, List indexDataList) | 索引插入 |
public List update(String groupId, String bundleName, List indexDataList) | 索引更新 | |
public List delete(String groupId, String bundleName, List indexDataList) | 索引删除 | |
SearchSession | public int getSearchHitCount(String queryJsonStr) | 搜索命中结果数量 |
public List search(String queryJsonStr, int start, int limit) | 分页搜索 | |
public List groupSearch(String queryJsonStr, int groupLimit) | 分组搜索 |
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);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。