tencent cloud

即时通信 IM

Android&iOS&Windows&Mac

下载
聚焦模式
字号
最后更新时间: 2025-03-24 10:36:51

功能描述

本地消息搜索,提升 App 使用体验必备功能,可以帮助用户从纷繁复杂的信息中直接找到预期内容,快捷方便;也可作为运营工具,增加相关内容的引导,简洁高效。
说明:
消息搜索只能搜索本地存储的消息,例如接收到的消息、调用拉取历史消息接口得到的消息等。
消息搜索功能仅增强版 SDK 5.4.666 及以上版本支持。
本地消息搜索为专业版、专业版Plus、企业版功能,购买专业版、专业版Plus、企业版后可使用。

消息搜索类介绍

消息搜索参数类

消息搜索参数类为 V2TIMMessageSearchParam(Java / Swift / Objective-C / C++)。搜索消息时,SDK 会按照该对象的设置,执行不同的搜索逻辑。
V2TIMMessageSearchParam 的参数说明如下:
参数
含义
说明
keywordList
关键字列表
最多支持 5 个。当消息发送者以及消息类型均未指定时,必须设置关键字列表;否则,关键字列表可以为空。
keywordListMatchType
指定关键字列表匹配类型
可设置为 “或” 关系搜索,或 “与” 关系搜索。取值分别为 V2TIM_KEYWORD_LIST_MATCH_TYPE_OR 和 V2TIM_KEYWORD_LIST_MATCH_TYPE_AND。默认为 “或” 关系搜索。
senderUserIDList
指定 userID 发送的消息
最多支持 5 个。
messageTypeList
指定搜索的消息类型集合
传空表示搜索支持的全部类型消息(V2TIMFaceElem 和 V2TIMGroupTipsElem 不支持搜索)。其他类型取值参考 V2TIMElemType(Java / Swift / Objective-C / C++)。
conversationID
搜索 “全部会话” 还是搜索 “指定的会话”
conversationID 为空,搜索全部会话;conversationID 不为空,搜索指定会话。
searchTimePosition
搜索的起始时间点
默认为 0(从现在开始搜索)。UTC 时间戳,单位:秒。
searchTimePeriod
从起始时间点开始的过去时间范围
默认为 0(不限制时间范围)。24x60x60 代表过去一天。单位:秒。
pageIndex
分页的页号
用于分页展示查找结果,0 表示首页。
pageSize
每页结果数量
用于分页展示查找结果,如不希望分页可将其设置成 0。但如果结果数量太多,一次性拉取可能会引发性能问题。

消息搜索结果类

消息搜索结果类为 V2TIMMessageSearchResult(Java / Swift / Objective-C / C++)。参数说明如下:
参数
含义
说明
totalCount
搜索结果总数
如果搜索指定会话,返回满足搜索条件的消息总数;
如果搜索全部会话,返回满足搜索条件的消息所在的所有会话总数量。
messageSearchResultItems
指定关键字列表匹配类型
如果搜索指定会话,返回结果列表只包含该会话结果;
如果搜索全部会话,会对满足搜索条件的消息根据会话 ID 分组,分页返回分组结果。
其中 messageSearchResultItems 是个列表,内含 V2TIMMessageSearchResultItem(Java / Swift / Objective-C / C++) 对象,参数说明如下:
参数
含义
说明
conversationID
会话 ID
——
messageCount
消息数量
当前会话一共搜索到了多少条符合要求的消息。
messageList
满足搜索条件的消息列表
如果搜索指定会话,messageList 中装载的是本会话中所有满足搜索条件的消息列表。
如果搜索全部会话,messageList 中装载的消息条数会有如下两种可能:
如果某个会话中匹配到的消息条数 > 1,则 messageList 为空,您可以在 UI 上显示 “{messageCount} 条相关记录”。
如果某个会话中匹配到的消息条数 = 1,则 messageList 为匹配到的那条消息,您可以在 UI 上显示之,并高亮匹配关键词。

搜索全部会话的消息

当用户在搜索框输入关键字搜索消息时,您可以调用 searchLocalMessages (Java / Swift / Objective-C / C++) 搜索 Chat SDK 本地存储的消息。
如果您希望在全部会话范围内搜索,只需要将 V2TIMMessageSearchParam 中的 conversationID 设置为空或者不设置即可。
示例代码如下:
Java
Swift
Objective-C
C++
List<String> keywordList = new ArrayList<>();
keywordList.add("abc");
keywordList.add("123");
V2TIMMessageSearchParam searchParam = new V2TIMMessageSearchParam();
// 设置搜索关键字
searchParam.setKeywordList(keywordList);
// 搜索第 0 页数据
searchParam.setPageIndex(0);
// 每页搜索 10 条数据
searchParam.setPageSize(10);
V2TIMManager.getMessageManager().searchLocalMessages(searchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
// 搜索成功
}

@Override
public void onError(int code, String desc) {
// 搜索失败
}
});
let param = V2TIMMessageSearchParam()
param.keywordList = ["key1", "key2"]
param.keywordListMatchType = .V2TIM_KEYWORD_LIST_MATCH_TYPE_AND
param.senderUserIDList = ["1", "2"]
param.messageTypeList = [.V2TIM_ELEM_TYPE_TEXT, .V2TIM_ELEM_TYPE_IMAGE]
param.searchTimePosition = 100
param.searchTimePeriod = 100
// 搜索第 0 页数据
param.pageIndex = 0
// 每页搜索 10 条数据
param.pageSize = 10

V2TIMManager.shared.searchLocalMessages(param: param) { searchResult in
print(searchResult.description)
} fail: { code, desc in
print("searchLocalMessages fail, \\(code), \\(desc)")
}
V2TIMMessageSearchParam *param = [[V2TIMMessageSearchParam alloc] init];
// 设置搜索关键字
param.keywordList = @[@"abc", @"123"];
param.messageTypeList = nil;
param.conversationID = nil;
param.searchTimePosition = 0;
param.searchTimePeriod = 0;
// 搜索第 0 页数据
param.pageIndex = 0;
// 每页搜索 10 条数据
param.pageSize = 10;
[V2TIMManager.sharedInstance searchLocalMessages:param
succ:^(V2TIMMessageSearchResult *searchResult) {
// 搜索成功,searchResult 中返回搜索结果
} fail:^(int code, NSString *desc) {
// 搜索失败
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageSearchParam searchParam;
// 设置搜索关键字
searchParam.keywordList.PushBack("abc");
searchParam.keywordList.PushBack("123");
// 搜索第 0 页数据
searchParam.pageIndex = 0;
// 每页搜索 10 条数据
searchParam.pageSize = 10;

auto callback = new ValueCallback<V2TIMMessageSearchResult>{};
callback->SetCallback(
[=](const V2TIMMessageSearchResult& messageSearchResult) {
// 搜索成功
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// 搜索失败
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->SearchLocalMessages(searchParam, callback);

搜索指定会话的消息

当用户在搜索框输入关键字搜索消息时,您可以调用 searchLocalMessages (Java / Swift / Objective-C / C++) 搜索 ChatSDK 本地存储的消息。
示例代码如下:
Java
Swift
Objective-C
C++
List<String> keywordList = new ArrayList<>();
keywordList.add("abc");
keywordList.add("123");
V2TIMMessageSearchParam searchParam = new V2TIMMessageSearchParam();
// 搜索与用户 user1 的单聊消息
searchParam.setConversationID("c2c_user1");
// 设置搜索关键字
searchParam.setKeywordList(keywordList);
// 搜索第 0 页数据
searchParam.setPageIndex(0);
// 每页搜索 10 条数据
searchParam.setPageSize(10);
V2TIMManager.getMessageManager().searchLocalMessages(searchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
// 搜索成功
}

@Override
public void onError(int code, String desc) {
// 搜索失败
}
});
let param = V2TIMMessageSearchParam()
param.keywordList = ["key1", "key2"]
// 搜索与用户 user1 的单聊消息
param.conversationID = "c2c_user1"
param.searchTimePosition = 0
param.searchTimePeriod = 0
// 搜索第 0 页数据
param.pageIndex = 0
// 每页搜索 10 条数据
param.pageSize = 10

V2TIMManager.shared.searchLocalMessages(param: param) { searchResult in
print(searchResult.description)
} fail: { code, desc in
print("searchLocalMessages fail, \\(code), \\(desc)")
}
V2TIMMessageSearchParam *param = [[V2TIMMessageSearchParam alloc] init];
// 设置搜索关键字
param.keywordList = @[@"abc", @"123"];
param.messageTypeList = nil;
// 搜索与用户 user1 的单聊消息
param.conversationID = @"c2c_user1";
param.searchTimePosition = 0;
param.searchTimePeriod = 0;
// 搜索第 0 页数据
param.pageIndex = 0;
// 每页搜索 10 条数据
param.pageSize = 10;
[V2TIMManager.sharedInstance searchLocalMessages:param
succ:^(V2TIMMessageSearchResult *searchResult) {
// 搜索成功,searchResult 中返回搜索结果
} fail:^(int code, NSString *desc) {
// 搜索失败
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageSearchParam searchParam;
// 搜索与用户 user1 的单聊消息
searchParam.conversationID = "c2c_user1";
// 设置搜索关键字
searchParam.keywordList.PushBack("abc");
searchParam.keywordList.PushBack("123");
// 搜索第 0 页数据
searchParam.pageIndex = 0;
// 每页搜索 10 条数据
searchParam.pageSize = 10;

auto callback = new ValueCallback<V2TIMMessageSearchResult>{};
callback->SetCallback(
[=](const V2TIMMessageSearchResult& messageSearchResult) {
// 搜索成功
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// 搜索失败
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->SearchLocalMessages(searchParam, callback);

搜索典型场景示例

普通的 Chat 聊天软件,搜索界面的展示通常分这几种场景:
图 1:搜索聊天记录
图 2:搜索更多聊天记录
图 3:搜索指定会话的消息









下文我们将依次向您展示如何利用 Chat SDK 的搜索 API 实现上图的典型场景。

展示最近几个活跃的会话

如图 1 所示,最下方是搜索到的消息所属的最近 3 个会话列表,实现方式如下:
1. 设置搜索参数 V2TIMMessageSearchParam
conversationID 设置为 null,表示搜索所有会话的消息。
pageIndex 设置为 0,表示搜索到的消息所属的会话的首页数据。
pageSize 设置为 3,表示返回最近的会话数量,UI 上一般显示 3 条。
2. 处理搜索回调结果 V2TIMMessageSearchResult
totalCount 表示匹配到的消息所属的所有会话数量。
messageSearchResultItems 列表为最近 3(即入参 pageSize)个会话信息。其中元素 V2TIMMessageSearchResultItem 的 messageCount 表示当前会话搜索到的消息总数量;
搜索到的消息条数 > 1,则 messageList 为空,您可以在 UI 上显示 “4 条相关聊天记录”,其中的 4 为 messageCount。
搜索到的消息条数 = 1,则 messageList 为匹配到的那条消息,您可以在 UI 上显示消息内容并高亮搜索关键词,例如图中的 “test”。
示例代码如下:
Java
Swift
Objective-C
C++
List<String> keywordList = new ArrayList<>();
keywordList.add("test");
V2TIMMessageSearchParam v2TIMMessageSearchParam = new V2TIMMessageSearchParam();
// conversationID 设置为 null 表示搜索所有会话中的消息,结果会按照会话分类
v2TIMMessageSearchParam.setConversationID(null);
v2TIMMessageSearchParam.setKeywordList(keywordList);
v2TIMMessageSearchParam.setPageSize(3);
v2TIMMessageSearchParam.setPageIndex(0);
V2TIMManager.getMessageManager().searchLocalMessages(v2TIMMessageSearchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
// 匹配到的消息所属的所有会话数量
int totalCount = v2TIMMessageSearchResult.getTotalCount();
// 最近3个根据消息会话分类的信息
List<V2TIMMessageSearchResultItem> resultItemList = v2TIMMessageSearchResult.getMessageSearchResultItems();
for (V2TIMMessageSearchResultItem resultItem : resultItemList) {
// 会话 ID
String conversationID = resultItem.getConversationID();
// 该会话匹配到的所有消息数量
int totalMessageCount = resultItem.getMessageCount();
// 消息列表:如果 totalMessageCount > 1,该列表为空;如果 totalMessageCount = 1,该列表元素为此消息
List<V2TIMMessage> v2TIMMessageList = resultItem.getMessageList();
}
}

@Override
public void onError(int code, String desc) {}
});
let param = V2TIMMessageSearchParam()
param.keywordList = ["test"]
// conversationID 设置为 nil 表示搜索所有会话中的消息,结果会按照会话分类
param.conversationID = nil
param.pageIndex = 0
param.pageSize = 3

V2TIMManager.shared.searchLocalMessages(param: param, succ: { searchResult in
// 匹配到的消息所属的所有会话数量
let totalCount = searchResult.totalCount
// 最近3个根据消息会话分类的信息
let messageSearchResultItems = searchResult.messageSearchResultItems
for searchItem in messageSearchResultItems {
// 会话 ID
let conversationID = searchItem.conversationID
// 该会话匹配到的所有消息数量
let messageCount = searchItem.messageCount
// 消息列表
let messageList = searchItem.messageList ?? []
}
}, fail: { code, desc in
// fail
})

V2TIMMessageSearchParam *param = [[V2TIMMessageSearchParam alloc] init];
param.keywordList = @[@"test"];
// conversationID 设置为 nil 表示搜索所有会话中的消息,结果会按照会话分类
param.conversationID = nil;
param.pageIndex = 0;
param.pageSize = 3;
[V2TIMManager.sharedInstance searchLocalMessages:param succ:^(V2TIMMessageSearchResult *searchResult) {
// 匹配到的消息所属的所有会话数量
NSInteger totalCount = searchResult.totalCount;
// 最近3个根据消息会话分类的信息
NSArray<V2TIMMessageSearchResultItem *> *messageSearchResultItems = searchResult.messageSearchResultItems;
for (V2TIMMessageSearchResultItem *searchItem in messageSearchResultItems) {
// 会话 ID
NSString *conversationID = searchItem.conversationID;
// 该会话匹配到的所有消息数量
NSUInteger messageCount = searchItem.messageCount;
// 消息列表
NSArray<V2TIMMessage *> *messageList = searchItem.messageList ?: @[];
}
} fail:^(int code, NSString *desc) {
// fail
}];
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

V2TIMMessageSearchParam searchParam;
// conversationID 设置为空表示搜索所有会话中的消息,结果会按照会话分类
searchParam.conversationID = {};
searchParam.keywordList.PushBack("test");
searchParam.pageIndex = 0;
searchParam.pageSize = 3;

auto callback = new ValueCallback<V2TIMMessageSearchResult>{};
callback->SetCallback(
[=](const V2TIMMessageSearchResult& messageSearchResult) {
// 匹配到的消息所属的所有会话数量
uint32_t totalCount = messageSearchResult.totalCount;
// 最近3个根据消息会话分类的信息
V2TIMMessageSearchResultItemVector messageSearchResultItems =
messageSearchResult.messageSearchResultItems;
for (size_t i = 0; i < messageSearchResultItems.Size(); ++i) {
// 会话 ID
V2TIMString conversationID = messageSearchResultItems[i].conversationID;
// 该会话匹配到的所有消息数量
uint32_t messageCount = messageSearchResultItems[i].messageCount;
// 消息列表:如果 messageCount > 1,该列表为空;如果 messageCount = 1,该列表元素为此消息
V2TIMMessageVector messageList = messageSearchResultItems[i].messageList;
}
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// 搜索失败
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->SearchLocalMessages(searchParam, callback);

展示所有搜索到的消息所属会话列表

点击图 1 中的 “更多聊天记录”,会跳转到图 2,展示所有搜索到的消息所属的会话列表。搜索参数和搜索结果描述跟上文的场景类似。
为了防止内存膨胀,我们强烈建议您分页加载会话列表。 举个例子,分页加载,每页展示 10 条会话结果,搜索参数 V2TIMMessageSearchParam 可以参考如下设置:
1. 首次调用:设置参数 pageSize = 10,pageIndex = 0。调用 searchLocalMessages 获取消息搜索结果,解析并展示到首页,并且从结果回调中的 totalCount 获取会话总数量。
2. 计算页数:totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1) 。
3. 再次调用:可以通过设置参数 pageIndex(pageIndex < totalPage)查询后续指定页数的搜索结果。
示例代码如下:
Java
Swift
Objective-C
C++
......
// 每页展示数量为10条,计算总页数
int totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
......

private void searchConversation(int index) {
if (index >= totalPage) {
return;
}
List<String> keywordList = new ArrayList<>();
keywordList.add("test");
V2TIMMessageSearchParam v2TIMMessageSearchParam = new V2TIMMessageSearchParam();
v2TIMMessageSearchParam.setConversationID(null);
v2TIMMessageSearchParam.setKeywordList(keywordList);
v2TIMMessageSearchParam.setPageSize(10);
v2TIMMessageSearchParam.setPageIndex(index);
V2TIMManager.getMessageManager().searchLocalMessages(v2TIMMessageSearchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
// 匹配到的消息所属的所有会话数量
int totalCount = v2TIMMessageSearchResult.getTotalCount();
// 每页展示数量为10条,计算总页数
int totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
// 该页的根据消息会话分类的信息
List<V2TIMMessageSearchResultItem> resultItemList = v2TIMMessageSearchResult.getMessageSearchResultItems();
for (V2TIMMessageSearchResultItem resultItem : resultItemList) {
// 会话 ID
String conversationID = resultItem.getConversationID();
// 该会话匹配到的所有消息数量
int totalMessageCount = resultItem.getMessageCount();
// 消息列表:如果 totalMessageCount > 1,该列表为空;如果 totalMessageCount = 1,该列表元素为此消息
List<V2TIMMessage> v2TIMMessageList = resultItem.getMessageList();
}
}

@Override
public void onError(int code, String desc) {}
});
}

// 当需要加载下一页时
public void loadMore() {
searchConversation(++pageIndex);
}
......
// 每页展示数量为10条,计算总页数
let totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1)
......
func searchConversation(index: UInt) {
if index >= totalPage {
return
}
let param = V2TIMMessageSearchParam()
param.keywordList = ["test"]
param.conversationID = nil
param.pageIndex = index
param.pageSize = 10
V2TIMManager.shared.searchLocalMessages(param: param, succ: { searchResult in
// 匹配到的消息所属的所有会话数量
let totalCount = searchResult.totalCount
// 每页展示数量为10条,计算总页数
let totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1)
// 该页的根据消息会话分类的信息
let messageSearchResultItems = searchResult.messageSearchResultItems
for searchItem in messageSearchResultItems {
// 会话 ID
let conversationID = searchItem.conversationID
// 该会话匹配到的所有消息数量
let totalMessageCount = searchItem.messageCount
// 消息列表:如果 totalMessageCount > 1,该列表为空;如果 totalMessageCount = 1,该列表元素为此消息
let messageList = searchItem.messageList ?? []
}
}, fail: { code, desc in
// fail
})
}

// 当需要加载下一页时
func loadMore() {
pageIndex += 1
searchConversation(index: pageIndex)
}
......
// 每页展示数量为10条,计算总页数
NSInteger totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
......

- (void)searchConversation:(NSUInteger)index {
if (index >= totalPage) {
return;
}
V2TIMMessageSearchParam *param = [[V2TIMMessageSearchParam alloc] init];
param.keywordList = @[@"test"];
param.conversationID = nil;
param.pageIndex = index;
param.pageSize = 10;
[V2TIMManager.sharedInstance searchLocalMessages:param succ:^(V2TIMMessageSearchResult *searchResult) {
// 匹配到的消息所属的所有会话数量
NSUInteger totalCount = searchResult.totalCount;
// 每页展示数量为10条,计算总页数
NSUInteger totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
// 该页的根据消息会话分类的信息
NSArray<V2TIMMessageSearchResultItem *> *messageSearchResultItems = searchResult.messageSearchResultItems;
for (V2TIMMessageSearchResultItem *searchItem in messageSearchResultItems) {
// 会话 ID
NSString *conversationID = searchItem.conversationID;
// 该会话匹配到的所有消息数量
NSUInteger totalMessageCount = searchItem.messageCount;
// 消息列表:如果 totalMessageCount > 1,该列表为空;如果 totalMessageCount = 1,该列表元素为此消息
NSArray<V2TIMMessage *> *messageList = searchItem.messageList ?: @[];
}
} fail:^(int code, NSString *desc) {
// fail
}];
}

// 当需要加载下一页时
- (void)loadMore {
[self searchConversation:++pageIndex];
}
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// 每页展示数量为10条,计算总页数
uint32_t totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);

void SearchConversation(uint32_t index) {
if (index >= totalPage) {
return;
}

V2TIMMessageSearchParam searchParam;
searchParam.keywordList.PushBack("test");
searchParam.pageIndex = index;
searchParam.pageSize = 10;

auto callback = new ValueCallback<V2TIMMessageSearchResult>{};
callback->SetCallback(
[=](const V2TIMMessageSearchResult& messageSearchResult) {
// 匹配到的消息所属的所有会话数量
uint32_t totalCount = messageSearchResult.totalCount;
// 每页展示数量为10条,计算总页数
uint32_t totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
// 该页的根据消息会话分类的信息
V2TIMMessageSearchResultItemVector messageSearchResultItems =
messageSearchResult.messageSearchResultItems;
for (size_t i = 0; i < messageSearchResultItems.Size(); ++i) {
// 会话 ID
V2TIMString conversationID = messageSearchResultItems[i].conversationID;
// 该会话匹配到的所有消息数量
uint32_t messageCount = messageSearchResultItems[i].messageCount;
// 消息列表:如果 messageCount > 1,该列表为空;如果 messageCount = 1,该列表元素为此消息
V2TIMMessageVector messageList = messageSearchResultItems[i].messageList;
}
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// 搜索失败
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->SearchLocalMessages(searchParam, callback);
}

// 当需要加载下一页时
void LoadMore() { SearchConversation(++pageIndex); }

展示搜索指定会话的消息

与图 2 展示会话列表不同的是,图 3 所示在指定会话中搜索到的消息列表。 为了防止内存膨胀,我们强烈建议您分页加载消息。举个例子,分页加载,每页展示 10 条消息结果:
1. 搜索参数 V2TIMMessageSearchParam 可以参考如下设置(pageIndex 的计算与上一节一致):
设置搜索参数 V2TIMMessageSearchParam 的 conversationID 为搜索的会话 ID。
首次调用:设置参数 pageSize = 10,pageIndex = 0。调用 searchLocalMessages 获取消息搜索结果,解析并展示到首页,并且从结果回调中的 totalCount 获取会话总数量。
计算页数:totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize + 1) 。
再次调用:可以通过设置参数 pageIndex(pageIndex < totalPage)查询后续指定页数的搜索结果。
2. 处理搜索结果 V2TIMMessageSearchResult:
totalCount 表示该会话匹配到的所有消息数量。
messageSearchResultItems 列表只有该会话的结果。列表中的元素 V2TIMMessageSearchResultItem 的 messageCount 为该分页的消息数量,messageList 为该分页的消息列表。
示例代码如下:
Java
Swift
Objective-C
C++
......
// 每页展示数量为10条,计算总页数
int totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1);
......

private void searchMessage(int index) {
if (index >= totalMessagePage) {
return;
}
List<String> keywordList = new ArrayList<>();
keywordList.add("test");
V2TIMMessageSearchParam v2TIMMessageSearchParam = new V2TIMMessageSearchParam();
v2TIMMessageSearchParam.setConversationID(conversationID);
v2TIMMessageSearchParam.setKeywordList(keywordList);
v2TIMMessageSearchParam.setPageSize(10);
v2TIMMessageSearchParam.setPageIndex(index);
V2TIMManager.getMessageManager().searchLocalMessages(v2TIMMessageSearchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
// 该会话匹配到的所有消息数量
int totalMessageCount = v2TIMMessageSearchResult.getTotalCount();
// 每页展示数量为10条,计算总页数
int totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1);
// 该页消息信息
List<V2TIMMessageSearchResultItem> resultItemList = v2TIMMessageSearchResult.getMessageSearchResultItems();
for (V2TIMMessageSearchResultItem resultItem : resultItemList) {
// 会话 ID
String conversationID = resultItem.getConversationID();
// 该页的消息数量
int totalMessageCount = resultItem.getMessageCount();
// 该页的消息数据列表
List<V2TIMMessage> v2TIMMessageList = resultItem.getMessageList();
}
}

@Override
public void onError(int code, String desc) {
}
});
}
// 当需要加载下一页时
public void loadMore() {
searchMessage(++pageIndex);
}
......
// 每页展示数量为10条,计算总页数
let totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1)
......
func searchMessage(index: UInt) {
if index >= totalMessagePage {
return
}
let param = V2TIMMessageSearchParam()
param.keywordList = ["test"]
param.conversationID = "conversationID"
param.pageIndex = index
param.pageSize = 10
V2TIMManager.shared.searchLocalMessages(param: param, succ: { searchResult in
// 该会话匹配到的所有消息数量
let totalMessageCount = searchResult.totalCount
// 每页展示数量为10条,计算总页数
let totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1)
// 该页消息信息
let messageSearchResultItems = searchResult.messageSearchResultItems
for searchItem in messageSearchResultItems {
// 会话 ID
let conversationID = searchItem.conversationID
// 该页的消息数量
let totalMessageCount = searchItem.messageCount
// 该页的消息数据列表
let messageList = searchItem.messageList ?? []
}
}, fail: { code, desc in
// fail
})
}

// 当需要加载下一页时
func loadMore() {
pageIndex += 1
searchMessage(index: pageIndex)
}
......
// 每页展示数量为10条,计算总页数
NSInteger totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1);
......

- (void)searchMessage:(NSUInteger)index {
if (index >= totalMessagePage) {
return;
}
V2TIMMessageSearchParam *param = [[V2TIMMessageSearchParam alloc] init];
param.keywordList = @[@"test"];
param.conversationID = conversationID;
param.pageIndex = index;
param.pageSize = 10;
[V2TIMManager.sharedInstance searchLocalMessages:param succ:^(V2TIMMessageSearchResult *searchResult) {
// 该会话匹配到的所有消息数量
NSUInteger totalMessageCount = searchResult.totalCount;
// 每页展示数量为10条,计算总页数
NSUInteger totalMessagePage = (totalMessageCount % 10 == 0) ? (totalMessageCount / 10) : (totalMessageCount / 10 + 1);
// 该页消息信息
NSArray<V2TIMMessageSearchResultItem *> *messageSearchResultItems = searchResult.messageSearchResultItems;
for (V2TIMMessageSearchResultItem *searchItem in messageSearchResultItems) {
// 会话 ID
NSString *conversationID = searchItem.conversationID;
// 该页的消息数量
NSUInteger totalMessageCount = searchItem.messageCount;
// 该页的消息数据列表
NSArray<V2TIMMessage *> *messageList = searchItem.messageList ?: @[];
}
} fail:^(int code, NSString *desc) {
// fail
}];
}

// 当需要加载下一页时
- (void)loadMore {
[self searchMessage:++pageIndex];
}
template <class T>
class ValueCallback final : public V2TIMValueCallback<T> {
public:
using SuccessCallback = std::function<void(const T&)>;
using ErrorCallback = std::function<void(int, const V2TIMString&)>;

ValueCallback() = default;
~ValueCallback() override = default;

void SetCallback(SuccessCallback success_callback, ErrorCallback error_callback) {
success_callback_ = std::move(success_callback);
error_callback_ = std::move(error_callback);
}

void OnSuccess(const T& value) override {
if (success_callback_) {
success_callback_(value);
}
}
void OnError(int error_code, const V2TIMString& error_message) override {
if (error_callback_) {
error_callback_(error_code, error_message);
}
}

private:
SuccessCallback success_callback_;
ErrorCallback error_callback_;
};

// 每页展示数量为10条,计算总页数
uint32_t totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);

void SearchConversation(uint32_t index) {
if (index >= totalPage) {
return;
}

V2TIMMessageSearchParam searchParam;
searchParam.conversationID = conversationID;
searchParam.keywordList.PushBack("test");
searchParam.pageIndex = index;
searchParam.pageSize = 10;

auto callback = new ValueCallback<V2TIMMessageSearchResult>{};
callback->SetCallback(
[=](const V2TIMMessageSearchResult& messageSearchResult) {
// 该会话匹配到的所有消息数量
uint32_t totalCount = messageSearchResult.totalCount;
// 每页展示数量为10条,计算总页数
uint32_t totalPage = (totalCount % 10 == 0) ? (totalCount / 10) : (totalCount / 10 + 1);
// 该页消息信息
V2TIMMessageSearchResultItemVector messageSearchResultItems =
messageSearchResult.messageSearchResultItems;
for (size_t i = 0; i < messageSearchResultItems.Size(); ++i) {
// 会话 ID
V2TIMString conversationID = messageSearchResultItems[i].conversationID;
// 该页的消息数量
uint32_t messageCount = messageSearchResultItems[i].messageCount;
// 该页的消息数据列表
V2TIMMessageVector messageList = messageSearchResultItems[i].messageList;
}
delete callback;
},
[=](int error_code, const V2TIMString& error_message) {
// 搜索失败
delete callback;
});

V2TIMManager::GetInstance()->GetMessageManager()->SearchLocalMessages(searchParam, callback);
}

// 当需要加载下一页时
void LoadMore() { SearchConversation(++pageIndex); }

搜索自定义消息

通常情况下,如果您使用接口 createCustomMessage(data) (Java / Swift / Objective-C / C++) 创建自定义消息,该消息无法被搜到,因为 SDK 将该自定义消息保存为二进制数据流。
如果您希望自定义消息可以被搜到,需要使用接口 createCustomMessage(data, description, extension) (Java / Swift / Objective-C / C++) 来创建并发送自定义消息,把需要搜索的文本放到 description 参数中。
如果您配置了离线推送功能,设置参数 description 后,自定义消息也会有离线推送且通知栏展示该参数内容。 如果不需要离线推送可以用发消息接口 sendMessage (Java / Swift / Objective-C / C++) 的参数 V2TIMOfflinePushInfo 中的 disablePush 来控制。
如果推送的通知栏内容不想展示为被搜索的文本,可以用参数 V2TIMOfflinePushInfo 中的 desc 来另外设置推送内容。

搜索富媒体消息

富媒体消息包含文件、图片、语音、视频消息。
对于文件消息,界面通常显示文件名。如果调用 createFileMessage 创建文件消息时传入 fileName 参数,fileName 会作为文件消息被搜索的内容,与搜索关键词进行匹配。如果未设置 fileName,SDK 则会自动从 filePath 提取文件名作为搜索内容。 fileName 和 filePath 信息会保存到本地和服务器,换设备拉取相关信息后均可搜索。
对于图片、语音、视频消息,并没有类似 fileName 这种名称,界面通常显示缩略图或时长,此时指定 keywordList 搜索无效。 如果您希望搜索出此类消息,可以指定 messageTypeList 为 V2TIM_ELEM_TYPE_IMAGE/V2TIM_ELEM_TYPE_SOUND/V2TIM_ELEM_TYPE_VIDEO 做分类搜索,此时会搜索出所有指定类型的消息。

帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈