有个 Go 项目用的 MongoDB,因为所以种种原因,决定把数据库换成 PostgreSQL。项目代码量不小,各种增删改查、聚合函数满天飞,纯手工改,一个字"累"。正好最近在玩OpenClaw,就想试试能不能帮上忙。
开始用了阿里百炼CodingPlan的Qwen3.5-Plus,结果翻车了。后来看网上说刚发布的 Qwen3.6-Plus 编程能力提升很大,效果直追claude-opus-4.6,加上OpenRouter上刚好有免费的Qwen3.6-Plus(免费用户50次/天,充值10美元解锁1000次/天免费额度),于是就重新来一遍试试,对比还是挺明显的。
一、Qwen3.5-plus
需求很简单:把项目里所有 MongoDB 的操作替换成 PostgreSQL 的写法。AI 干得挺麻利,各种函数一替换重写,消耗了1亿+ Token,go build 一跑——零报错,编译通过。当时心想这不挺好吗。结果一测接口,芭比 Q 了。
1. 字段大小写
MongoDB 那边字段名用的驼峰命名,userName、createTime、orderAmount 一堆。AI 改 PG 的时候,直接把字段名原样搬过去了。
但 PostgreSQL 默认列名是转小写的。你不加双引号,userName 存进去变成 username。查询的时候 AI 生成的 SQL 还是 userName,没加引号,PG 就去找 username——找得到才怪。
这不是语法问题,是理解差异。AI 只是做函数层面的替换,根本没意识到命名规范变了。
2. user 表名
项目里有张表叫 user。在 MongoDB 里这名字啥事没有。但 PostgreSQL 里 USER 是保留关键字。
AI 生成的 SQL 直接写的:
SELECT * FROM user WHERE id = 1;
查出来空的。因为 PG 把 user 当关键字处理了,正确的写法应该是 "user" 或者换个表名。
这种坑有 PG 经验的人一眼就看出来,但 AI 不知道,它没踩过。
3. 调用层只翻译不适配
这块问题最大。MongoDB 是文档数据库,PostgreSQL 是关系型数据库,数据模型根本不一样。但 AI 改代码的方式是添加了一个pg包,用MongoDB的接口参数,调用PostgreSQL语法实现对应的功能,调用层由原来的mongo-driver驱动换成了pg包对应的函数:
- 写一个
Table结构体替换MongoDB中的Collection
// Table 表结构
type Table struct {
name string
db *Conf
}
- 然后在Table中添加增删改查、聚合等方法。如:
// FindOne 查询单条记录
func (t *Table) FindOne(ctx context.Context, filter map[string]interface{}) (map[string]interface{}, error) {
var conditions []string
var values []interface{}
i := 1
for k, v := range filter {
conditions = append(conditions, k+" = $"+string(rune('0'+i)))
values = append(values, v)
i++
}
query := fmt.Sprintf("SELECT * FROM %s WHERE %s LIMIT 1",
t.name,
strings.Join(conditions, " AND "))
rows, err := t.db.pool.Query(ctx, query, values...)
if err != nil {
return nil, err
}
defer rows.Close()
if !rows.Next() {
return nil, fmt.Errorf("no rows")
}
cols := rows.FieldDescriptions()
vals := make([]interface{}, len(cols))
for i := range vals {
vals[i] = new(interface{})
}
if err := rows.Scan(vals...); err != nil {
return nil, err
}
rowMap := make(map[string]interface{})
for i, col := range cols {
rowMap[col.Name] = *vals[i].(*interface{})
}
return rowMap, nil
}
- 然后将
pg.Collection("user").FindOne()替换mdb.Collection("user").FindOne(),对于简单数据类型查找没问题。MongoDB 里的嵌套文档,PG 这边得展平成多张表或者用 JSON 字段,这样查出来的值就不对了。 - 聚合管道(
aggregate)里的$group、$lookup,在 PG 里对应的是GROUP BY、LEFT JOIN,虽然转了很多,还是同样的问题复杂数据就翻车了。
最终结果
go build 没问题,但每个接口跑起来都得手动排查、手动改。改了几个文件我放弃了,直接还原了。
二、Qwen3.6-Plus
今天用Qwen3.6-Plus,同一个项目、同一套需求,再来了一遍。这次前面出现的三个问题都有妥善解决。
1. 字段映射处理更细了
将驼峰命名法转成了蛇形命名,从数据库表到代码都改了。
2. 保留关键字会处理了
对于"user"这类表名,会主动加双引用了。
3. 调用层做了适配
不在集中封装个pg包 集体替换,而是每次数据库调用层都根据逻辑单独改成PG语法来实现。
也不是完美
MongoDB中多次层数据,没有它逻辑分表处理,而是直接用PG中的JSONB存了,在逻辑层对数据做处理。
最终效果
最终 MongoDB 到 PostgreSQL 的数据迁移跑完了,600 多万条记录全部导入成功,数据校验通过,本地大致测试了一下,没什么大的坑,但总体感觉是:从"编译通过但到处是坑"变成了"大致逻辑没问题,修修补补就能用"。,接下来还是要把AI改的代码过一遍,关键的验证和边界情况还是要人把关才放心。
对比
| Qwen3.5-Plus | Qwen3.6-Plus | |
|---|---|---|
| 编译 | 通过 | 通过 |
| 字段大小写 | 没管 | 基本处理了 |
| 保留关键字 | 直接裸写,查不到 | 会加引号 |
| 调用层逻辑 | 几乎不动 | 会适配调整 |
| 人工修复量 | 看到一半放弃了 | 第一次用AI改代码不放心还是要过一遍代码,但改动地方不多 |
总结
这次实测下来,Qwen3.6-Plus 在编程任务上的提升是能明显感觉到的,不是那种光喊口号的宣传。同一个活,两次体验差挺多。
但它现在还远没到能完全替代人的地步,不过我挺满意的。AI 把最枯燥的替换和翻译接过去,从写代码变成了审核代码,然后就能把精力放在真正需要动脑的地方。这才是 AI 辅助编程该有的样子吧。
对我们白嫖党的普通开发者来说,现在的 Qwen3.6-Plus 已经很能打了,不知道Qwen3.6-Plus还能免费多久,能薅一点算一点。
评论区