//聊天记录结构
type chat_list struct {
Createat int `json:"create_at"`
ToUid int64 `json:"to_uid"`
Uid int `json:"uid"`
Content string `json:"content"`
}
skip := (req.Page - 1) * req.PageSize
boolQuery := elastic.NewBoolQuery()
subQuery1 := elastic.NewBoolQuery().
Must(elastic.NewTermQuery("to_uid", req.StreamerId)).
Must(elastic.NewTermQuery("uid", req.MemberId))
subQuery2 := elastic.NewBoolQuery().
Must(elastic.NewTermQuery("to_uid", req.MemberId)).
Must(elastic.NewTermQuery("uid", req.StreamerId))
boolQuery = boolQuery.Should(subQuery1, subQuery2).MinimumShouldMatch("1")
searchResult, err := types.EsClient.Search().
Index(types.LU_CHANT_INDEX).
Query(boolQuery).
Sort("create_at", true).
From(skip). //第几页
Size((*req).PageSize). //每页多少条
Pretty(true).//返回json
Do(ctx)
if searchResult.TotalHits() < 1{
resp.List = make([]iapi.GuildStreamerChatList,0)
return
}
var chat_detail chat_list
//var member_id int64
for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) {
//主播为接收者,uid一定为会员
if (*req).StreamerId == item.ToUid{
member_id = item.Uid()
}
if (*req).StreamerId == item.Uid{
member_id = item.ToUid
}
break
}
通过for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) 解析数据到chat_detail里,报错:item.ToUid undefined (type interface{} has no field or method ToUid)
golang es查询解析到struct
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
4条回答 默认 最新
檀越@新空间 2025-09-18 11:18关注上午好☀️☀️☀️️
本答案参考通义千问你遇到的问题是:在使用
searchResult.Each(reflect.TypeOf(chat_detail))时,返回的item是一个interface{}类型,而不是你定义的chat_list结构体类型。因此,当你尝试访问item.ToUid或item.Uid()时,Go 编译器会报错,因为它无法识别这些字段或方法。
✅ 解决方案
1. 正确解析 ES 查询结果到结构体
你需要将
item转换为你的结构体类型(即chat_list),然后再访问其字段。✅ 修改后的代码如下:
for _, item := range searchResult.Each(reflect.TypeOf(chat_list{})) { // 将 interface{} 转换为 chat_list chatItem, ok := item.(chat_list) if !ok { continue // 如果转换失败,跳过 } // 现在可以安全地访问 chatItem 的字段 if req.StreamerId == chatItem.ToUid { member_id = chatItem.Uid } else if req.StreamerId == chatItem.Uid { member_id = chatItem.ToUid } // 注意:此处的 break 可能会导致只处理第一条记录,根据需求调整 break }
2. 使用
SearchResult.Each更安全的方式searchResult.Each方法接受一个reflect.Type参数,用于指定你要反序列化的结构体类型。但要注意的是,它返回的是一个[]interface{},每个元素是一个interface{},你需要显式地将其转换为你的结构体类型。
3. 完整示例代码(修改后)
type chat_list struct { Createat int `json:"create_at"` ToUid int64 `json:"to_uid"` Uid int `json:"uid"` Content string `json:"content"` } skip := (req.Page - 1) * req.PageSize boolQuery := elastic.NewBoolQuery() subQuery1 := elastic.NewBoolQuery(). Must(elastic.NewTermQuery("to_uid", req.StreamerId)). Must(elastic.NewTermQuery("uid", req.MemberId)) subQuery2 := elastic.NewBoolQuery(). Must(elastic.NewTermQuery("to_uid", req.MemberId)). Must(elastic.NewTermQuery("uid", req.StreamerId)) boolQuery = boolQuery.Should(subQuery1, subQuery2).MinimumShouldMatch(1) searchResult, err := types.EsClient.Search(). Index(types.LU_CHANT_INDEX). Query(boolQuery). Sort("create_at", true). From(skip). Size(req.PageSize). Pretty(true). Do(ctx) if searchResult.TotalHits() < 1 { resp.List = make([]iapi.GuildStreamerChatList, 0) return } var chat_detail chat_list var member_id int64 for _, item := range searchResult.Each(reflect.TypeOf(chat_detail)) { chatItem, ok := item.(chat_list) if !ok { continue } if req.StreamerId == chatItem.ToUid { member_id = chatItem.Uid } else if req.StreamerId == chatItem.Uid { member_id = chatItem.ToUid } // 注意:此处的 break 可能导致只处理第一条记录,根据需求调整 break }
4. 其他建议
- 如果你希望获取所有匹配的聊天记录,不要使用
break,而是将每条记录收集到切片中。 - 如果你的
chat_list结构体字段名和 Elasticsearch 中的字段名不一致,需要确保 JSON 标签正确映射。 - 使用
elastic.NewTermQuery时注意字段是否是 keyword 类型(如to_uid和uid是否被索引为 keyword)。
✅ 总结
| 步骤 | 内容 | |------|------| | 1 | 使用
searchResult.Each(reflect.TypeOf(chat_list{}))获取结果 | | 2 | 将item显式转换为chat_list类型 | | 3 | 访问结构体字段(如chatItem.ToUid) | | 4 | 避免使用break,除非你只需要第一条记录 |如果你还有其他问题,比如如何批量读取所有记录,也可以继续问我!
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 如果你希望获取所有匹配的聊天记录,不要使用