showliuzp 2025-09-18 11:15 采纳率: 84.3%
浏览 2
已结题

golang es查询解析到struct


 
    //聊天记录结构
    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)

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-09-18 11:18
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你遇到的问题是:在使用 searchResult.Each(reflect.TypeOf(chat_detail)) 时,返回的 item 是一个 interface{} 类型,而不是你定义的 chat_list 结构体类型。因此,当你尝试访问 item.ToUiditem.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_uiduid 是否被索引为 keyword)。

    ✅ 总结

    | 步骤 | 内容 | |------|------| | 1 | 使用 searchResult.Each(reflect.TypeOf(chat_list{})) 获取结果 | | 2 | 将 item 显式转换为 chat_list 类型 | | 3 | 访问结构体字段(如 chatItem.ToUid) | | 4 | 避免使用 break,除非你只需要第一条记录 |

    如果你还有其他问题,比如如何批量读取所有记录,也可以继续问我!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 9月26日
  • 已采纳回答 9月18日
  • 创建了问题 9月18日