You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:使用Retrofit向Mlab发送含$addToSet的PUT请求遇阻

解决Retrofit发送mLab $addToSet PUT请求的问题

我之前也遇到过类似的情况,Postman能跑通但Retrofit里就出问题,大多是请求结构或者序列化的细节没处理好。结合你的场景,咱们一步步来解决:

1. 先确认依赖配置

确保你已经添加了Retrofit和Gson转换器(用来处理JSON序列化),在build.gradle里加上:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

2. 定义请求体数据类

MongoDB的$addToSet是带$符号的操作符,Gson默认不会自动识别这种字段,所以必须用@SerializedName显式指定:

// Kotlin版本
data class UpdateWalkRequest(
    @SerializedName("$addToSet") // 关键:转义$符号
    val addToSet: WalkUpdateData
)

data class WalkUpdateData(
    val completedWalks: String // 要添加的单条步道名称;如果要加多条,改成List<String>
)

如果是Java的话,对应的POJO类:

// Java版本
public class UpdateWalkRequest {
    @SerializedName("$addToSet")
    private WalkUpdateData addToSet;

    public UpdateWalkRequest(WalkUpdateData addToSet) {
        this.addToSet = addToSet;
    }

    // getter & setter
}

public class WalkUpdateData {
    private String completedWalks;

    public WalkUpdateData(String completedWalks) {
        this.completedWalks = completedWalks;
    }

    // getter & setter
}

3. 定义Retrofit接口

mLab的更新接口需要指定数据库名、集合名,还要带API密钥、查询条件(用来定位要更新的文档):

// Kotlin版本
interface MlabApiService {
    @PUT("databases/{dbName}/collections/{collectionName}")
    suspend fun updateUserCompletedWalks(
        @Path("dbName") dbName: String,
        @Path("collectionName") collectionName: String,
        @Query("apiKey") apiKey: String,
        @Query("q") query: String, // 查询条件,比如{"email":"test@gmail.com"}的字符串形式
        @Query("upsert") upsert: Boolean = false, // 可选:无匹配文档时是否插入
        @Body request: UpdateWalkRequest
    ): Response<Void>
}

Java版本的接口:

// Java版本
public interface MlabApiService {
    @PUT("databases/{dbName}/collections/{collectionName}")
    Call<Void> updateUserCompletedWalks(
        @Path("dbName") String dbName,
        @Path("collectionName") String collectionName,
        @Query("apiKey") String apiKey,
        @Query("q") String query,
        @Query("upsert") boolean upsert,
        @Body UpdateWalkRequest request
    );
}

4. 初始化Retrofit并发起请求

Kotlin(用协程)

// 创建Retrofit实例
val retrofit = Retrofit.Builder()
    .baseUrl("https://api.mlab.com/api/1/") // mLab的基础API地址
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val mlabApi = retrofit.create(MlabApiService::class.java)

// 发起请求
CoroutineScope(Dispatchers.IO).launch {
    // 注意:查询条件要转成JSON字符串,引号需要转义
    val query = "{\"email\":\"test@gmail.com\"}"
    val updateRequest = UpdateWalkRequest(WalkUpdateData("South Leinster Way"))

    val response = mlabApi.updateUserCompletedWalks(
        dbName = "你的数据库名",
        collectionName = "你的集合名",
        apiKey = "你的mLab API密钥",
        query = query,
        request = updateRequest
    )

    if (response.isSuccessful) {
        // 更新成功,回到主线程处理UI
        withContext(Dispatchers.Main) {
            // 比如弹出提示
        }
    } else {
        // 打印错误信息排查问题
        val errorMsg = response.errorBody()?.string()
        Log.e("MlabError", "更新失败: $errorMsg")
    }
}

Java(用回调)

// 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.mlab.com/api/1/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

MlabApiService mlabApi = retrofit.create(MlabApiService.class);

// 发起请求
String query = "{\"email\":\"test@gmail.com\"}";
UpdateWalkRequest request = new UpdateWalkRequest(new WalkUpdateData("South Leinster Way"));

Call<Void> call = mlabApi.updateUserCompletedWalks(
    "你的数据库名",
    "你的集合名",
    "你的mLab API密钥",
    query,
    false,
    request
);

call.enqueue(new Callback<Void>() {
    @Override
    public void onResponse(Call<Void> call, Response<Void> response) {
        if (response.isSuccessful()) {
            // 更新成功
        } else {
            try {
                String errorMsg = response.errorBody().string();
                Log.e("MlabError", "更新失败: " + errorMsg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onFailure(Call<Void> call, Throwable t) {
        t.printStackTrace();
    }
});

常见问题排查

  1. $addToSet字段未被识别:一定要用@SerializedName("$addToSet"),Gson默认不会处理带$的字段
  2. 查询参数q格式错误:必须是合法的JSON字符串,比如{"email":"test@gmail.com"}要转义成字符串形式传递
  3. 请求方法错误:mLab更新文档必须用PUT,并且要带q参数定位文档
  4. 权限问题:确保你的API密钥有该数据库的写入权限

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:22:10