如题,如何实现unicloud批量查重增加数据,实现某一字段重复的只保留一个
要求:必须要批量操作,因为数据量比较大,逐个查重并插入效率太低
当前直接在数据表创建唯一索引,并直接使用add添加,遇到重复会直接报错,并且停止插入
原生mongodb可以使用{ordered:false}忽略报错(重复)数据,继续插入,但unicloud并没有暴露这个配置
如题,如何实现unicloud批量查重增加数据,实现某一字段重复的只保留一个
要求:必须要批量操作,因为数据量比较大,逐个查重并插入效率太低
当前直接在数据表创建唯一索引,并直接使用add添加,遇到重复会直接报错,并且停止插入
原生mongodb可以使用{ordered:false}忽略报错(重复)数据,继续插入,但unicloud并没有暴露这个配置
比如你现在是用户表有多个手机号重复了,手机号字段为mobile
const $ = db.command.aggregate();
let {data} = await db.collection(xxx).aggregate().match(...).group({
_id:"$mobile",
count:$.sum(1),
ids:$.push("$_id")
}).end();
let ts = data.map(v=>{
return db.collection(xxx).where({
_id:db.command.in(v.ids.slice(1)) //保留一条记录
})
});
let res = await Promise.all(ts);
如果你要根据多个字段来去重
那就把group里的_id属性写成对象,比如:
group({
_id:{
mobile:"$mobile",
name:"$name"
},
count:$.sum(1),
ids:$.push("$_id")
})
我写了一个简单demo,模拟了你说的场景。前两天是没看清楚你的需求。
确实如果按照批量插入,重复的数据无法跳过。因为api失败的时候不知道插入成功的数据有哪些。
const db = uniCloud.database();
const dbCmd = db.command;
const $ = db.command.aggregate;
function getRanNum(min, max, fixedNum = 0, func = 'round') {
return Math[func]((Math.random() * (max - min) + min) * (10 ** fixedNum)) / (10 ** fixedNum);
}
module.exports = {
async fn() {
let len = 100;
let trans = await db.startTransaction();
let addData = Array.from(Array(len), (x, i) => {
return {
id: getRanNum(0, len),
}
});
try {
let result = {
inserted: 0,
ids: []
}
await (async function addFn(index = 0) {
let data = addData[index];
if (!data) return;
try {
let res = await trans.collection("test-log").add(data)
result.inserted++;
result.ids.push(res.id);
} catch (e) {}
return await addFn(index + 1);
})();
console.log("result: ", result);
await trans.commit();
return result;
} catch (e) {
console.log("e: ", e);
await trans.rollback();
throw e;
}
}
}
猫猫儿 (作者)
试了一下,还是一样的报错,还是不继续执行了
2022-07-09 16:36