本文为您介绍本地搜索功能、使用方法。全文的示例代码均以Android代码为例。

概述

AIMSDK中,消息和会话的搜索是基于本地数据的搜索,目前不支持服务端搜索,因此AIMSDK的搜索能力有以下几个特点:
  • 仅支持本地搜索,可搜索范围受到本地数据库存储消息和会话多少的限制。
  • 应用重装后首次登录,AIMSDK会拉取首屏会话及每条会话的最后一条消息(last message),该场景下,仅可搜索到首屏可看到的会话及消息。
  • AIMSDK支持多账号同时登录,搜索服务与账号绑定,即每个搜索服务仅能搜索本账号对应的消息和会话。
  • 搜索引擎采用分词进行搜索。
    • 对于英文或数字:以空格或标点符号作为分词进行搜索。

      例如:123,abc,可通过“12”或者“ab”进行搜索,“23”、“bc”无法搜出该消息。

    • 对于中文:每个汉字都可进行搜索。

      例如:你好钉钉,可通过“你”、“好钉”、“钉钉”搜出该消息。

  • 对于消息搜索,默认情况下仅可对文本消息进行搜索,其他类型消息如需参与搜索,需进行特殊处理。
搜索功能列表如下:
  • 搜索纯文本消息
  • 搜索消息并按照会话进行聚合
  • 搜索群名称
  • 搜索内容分页
  • 自定义搜索非文本消息
  • 按照类型搜索消息

使用方法

  • 获取搜索服务

    示例代码,如下所示:

    AIMPubSearchService searchService = 
        AIMPubModule.getModuleInstance(currentUserId()).getSearchService();
  • 消息搜索

    消息搜索分为纯文本消息搜索和非文本消息搜索,AIMSDK默认支持对纯文本消息的搜索。

    • 纯文本消息搜索,示例代码如下所示:
      AIMSearchChatContentParams params;
      // 从第0个开始获取
      params.offset = 0;
      // 最多获取20个
      params.maxNum = 20;
      // 搜索消息开始时间,未指定则从0开始
      params.startTime = 1582709555;
      // 搜索消息开始时间,未指定则到现在
      params.endTime = 1582709555;
      // 是否自动高亮关键字,返回的AIMSearchHighlightRange包含高亮位置信息
      params.isAutoHighLight = true;
      // 搜索关键字
      params.keyword = "ding";
      // 按时间倒序搜索
      params.isAsc = false;
      // 可选:搜索的会话范围
      params.appCids = {"cid_1", "cid2"};
      // 可选:指定消息发送者搜索
      params.senderIds = {user_1, user_2};
      searchService.searchChatContent(params, new AIMPubSearchChatContentListener() {
        @Override
        public void onSuccess(ArrayList<AIMPubSearchChatResult> arrayList, int i) {
          // 返回的搜索结果
        }
      
        @Override
        public void onFailure(DPSError dpsError) {}
      });

      关键数据结构:AIMPubSearchChatContentParams,如下表所示:

      字段 类型 含义
      keyword String 需要搜索的关键字。
      offset int 返回结果起始位置,用于搜索结果分页,offset >= 0,默认为第一页。
      maxNum int 单次返回结果个数, 0 < maxNum <= 1000,默认为20个。
      startTime long 搜索消息开始时间,未指定则从0开始。
      endTime long 搜索消息开始时间,未指定则到现在。
      isAutoHightlight boolean 是否自动高亮关键字,返回的AIMSearchHighlightRange包含高亮位置信息,默认值为true。
      isAsc boolean 时间顺序,默认为true(升序)。
      supportMsgTypes ArrayList<AIMMsgContentType> 需要查询的消息类型列表,如文本,图片,多媒体,自定义等,为空则仅查询文本类型。
      supportSubTypes ArrayList<Integer> 消息子类型。
      bizTags ArrayList<String> 需要查询的biz_tag列表,为空则查所有(biz_tag为调用方回写的biz_info)。
      appCids ArrayList<String> 需要查询的会话列表,为空则查所有。
      senderIds ArrayList<String> 需要查询的发送者列表,为空则差所有。
    • 非文本消息搜索

      非文本消息包含图片,语音,结构化,自定义消息等,如需参与搜索,需要对消息进行预处理。如对语音的识别,图像识别,自定义卡片的识别等,需要App侧对此类消息可搜索字段进行加工处理,如下所示:

      • 需要监听消息的入库回调,对需要的消息进行加工处理。
      • 对于历史消息,需要手动拉取消息,并进行处理。
      • 消息的可加工字段位biz_tag及biz_text。biz_tag及biz_text仅存储在本地,不会上传到服务端。

        biz_tag:用于指定业务类型,作为搜索条件。

        biz_text:用于指定搜索文本,作为搜索匹配内容。

      进行加工处理的示例代码,如下所示:
      AIMPubModule module = AIMPubModule.getModuleInstance(currentUserId);
      AIMPubMsgService service = module.getMsgService();
      
      service.addMsgListener(new AIMPubMsgListener() {
        @Override
        public void onAddedMessages(final ArrayList<AIMPubNewMessage> arrayList) {
          AIMLog.toastWrapper("onAdded");
        }
      
        @Override
        public void onRemovedMessages(ArrayList<AIMPubMessage> arrayList) {
          AIMLog.e("删除消息:size:" + arrayList.size());
          AIMLog.toastWrapper("onRemoved");
        }
      
        @Override
        public void onStoredMessages(ArrayList<AIMPubMessage> arrayList) {
          AIMLog.e("onStored:size:" + arrayList.size());
          // 当消息数据库内有消息添加时,触发该回调 包括发送,推送及拉取历史消息
          // 当新消息入库时,进行消息的再加工处理,更新可搜索字段
          AIMLog.toastWrapper("onStored");
          ArrayList<AIMPubMsgBizUpdateInfo> infos =
              new ArrayList<AIMPubMsgBizUpdateInfo>();
          for (AIMPubMessage message : arrayList) {
            if (message.content.content_type ==
                AIMMsgContentType::CONTENT_TYPE_AUDIO) {
              AIMPubMsgBizUpdateInfo info;
              info.appCid = message.appCid;
              info.localid = message.localid;
              info.updateMode = AIMMsgUpdateMode::UPDATE_BIZ_ALL;
              info.biz_info.biz_tag = "to_me";
              info.biz_info.biz_text = "text from voice";
              infos.add(info);
            } else {
              // Other msgs...
            }
          }
        }
        service.updateLocalMessagesBizInfo(infos, null);
      });
      搜索的示例代码,如下所示:
      AIMSearchChatContentParams params;
      // 搜索关键字
      params.keyword = "text from voice";
      // 搜索文本及语音类型消息
      params.supportMsgTypes = {AIMMsgContentType::CONTENT_TYPE_AUDIO,
                                AIMMsgContentType::CONTENT_TYPE_TEXT};
      searchService.searchChatContent(params, new AIMPubSearchChatContentListener() {
        @Override
        public void onSuccess(ArrayList<AIMPubSearchChatResult> arrayList, int i) {
          // 返回的搜索结果
        }
      
        @Override
        public void onFailure(DPSError dpsError) {}
      });

      关键数据结构:AIMPubMsgBizUpdateInfo,如下表所示:

      字段 类型 含义
      appCid String 会话ID。
      localId String 消息的localId。
      updateMode AIMMsgUpdateMode 消息更新模式,更新Text、Tag。
      bizInfo AIMMsgBizInfo biz信息:bizTag、bizText。
  • 搜索结果以会话聚合

    以会话聚合的含义是搜索结果中是匹配搜索的消息所在的会话以及该会话匹配的第一条消息。

    示例代码,如下所示:
    AIMPubSearchChatContantParams param = new AIMPubSearchChatContantParams();
    param.keyword = "keyword";
    param.isAsc = true;
    searchService.searchConversationByContent(
        param, new AIMPubSearchConvByContentListener() {
          @Override
          public void onSuccess(ArrayList<AIMPubSearchConversationResult> arrayList,
                                int i) {
            // 搜索结果
          }
    
          @Override
          public void onFailure(DPSError dpsError) {}
        });
    关键数据结构:AIMPubSearchConversationResult,如下表所示:
    字段 类型 含义
    conversation AIMPubConversation 匹配到的会话。
    firstMessage AIMPubMessage 匹配到的第一条消息。
    ranges ArrayList<AIMSearchHighlightRange> 消息的高亮位置。
  • 群名称搜索

    根据群名称搜索群会话。

    示例代码,如下所示:
    AIMSearchGroupParams param = new AIMSearchGroupParams();
    param.keyword = "keyword";
    AIMPubModule.getModuleInstance(currentUserId())
        .getSearchService()
        .searchGroupByName(param, new AIMPubSearchGroupByNameListener() {
          @Override
          public void onSuccess(ArrayList<AIMPubConversation> arrayList,
                                int totalCount) {
            // 搜索结果
            // totalCount 仅在params中offset = 0 时有效
          }
    
          @Override
          public void onFailure(DPSError dpsError) {}
        });
  • 搜索内容分页

    客户端可以选择搜索结果的起始位置,用于实现搜索结果的分页。

    示例代码,如下所示:
    // 获取第一页
    int pageCount(0);
    AIMSearchGroupParams param = new AIMSearchGroupParams();
    param.keyword = "keyword";
    // 从第0个开始获取
    param.offset = 0;
    // 一页20个
    param.maxNum = 20;
    searchService.searchChatContent(params, new AIMPubSearchChatContentListener() {
      @Override
      public void onSuccess(ArrayList<AIMPubSearchChatResult> arrayList,
                            int totalCount) {
        // 返回的搜索结果, totalCount为搜索结果总个数
        // 可以计算出总页数
        pagecount = totalCount / 20;
            if(pageCount % 20 > 0) {
                pageCount = pageCount + 1;
            }
      }
    
      @Override
      public void onFailure(DPSError dpsError) {}
    });
    
    // 获取第二页
    param.offset = 20 * 1;
    param.maxNum = 20;
    searchService.searchChatContent(params, new AIMPubSearchChatContentListener() {
      @Override
      public void onSuccess(ArrayList<AIMPubSearchChatResult> arrayList,
                            int totalCount) {
        // 返回的搜索结果, totalCount没有意义(因为offset不是0)
      }
    
      @Override
      public void onFailure(DPSError dpsError) {}
    });