猫猫儿
猫猫儿
  • 发布:2022-07-09 11:21
  • 更新:2023-11-22 14:15
  • 阅读:1041

如何实现unicloud批量查重增加数据

分类:uniCloud

如题,如何实现unicloud批量查重增加数据,实现某一字段重复的只保留一个
要求:必须要批量操作,因为数据量比较大,逐个查重并插入效率太低

当前直接在数据表创建唯一索引,并直接使用add添加,遇到重复会直接报错,并且停止插入
原生mongodb可以使用{ordered:false}忽略报错(重复)数据,继续插入,但unicloud并没有暴露这个配置

2022-07-09 11:21 负责人:DCloud_uniCloud_WYQ 分享
已邀请:
风之源

风之源

db.collection(xxxx).add(data).then(e=>{ })
用异步写法,不要用await

  • 猫猫儿 (作者)

    试了一下,还是一样的报错,还是不继续执行了

    2022-07-09 16:36

雷峰

雷峰

比如你现在是用户表有多个手机号重复了,手机号字段为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")  
})
  • 猫猫儿 (作者)

    谢谢你,但是我是增加时查重,不是查询时查重

    2022-07-09 16:38

  • 雷峰

    回复 猫猫儿: 重复的数据清理掉,把唯一字段加上索引。再重复的时候就会自动抛出错误。如果你不想预先处理重复数据,那就在新增的时候按照我上面的方法查询一遍,然后清除多余的数据。

    2022-07-09 16:46

DCloud_uniCloud_WYQ

DCloud_uniCloud_WYQ

如果只是想继续插入的话,报错的时候catch一下不好了吗?

  • 猫猫儿 (作者)

    catch了不会继续插入了啊,我这是批量传了一个数组,并不是一个个循环添加,因为后者虽然可以catch但效率太低

    2022-07-11 16:49

  • DCloud_uniCloud_WYQ

    回复 猫猫儿: 需求已了解,我们看下如何实现

    2022-07-11 20:08

  • 1***@qq.com

    回复 DCloud_uniCloud_WYQ: 咋样了, 可以实现吗

    2023-07-27 02:10

雷峰

雷峰

我写了一个简单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-11 16:36

  • 猫猫儿 (作者)

    回复 雷峰: 我是一次至少50个,之后可能还会加,我先研究一下你的,谢谢

    2022-07-11 16:51

6***@qq.com

6***@qq.com

解决了吗?

要回复问题请先登录注册