Javin
Javin
  • 发布:2023-07-12 15:12
  • 更新:2023-07-13 11:19
  • 阅读:217

一段时间不用好像db.collection发生了bug?

分类:uniCloud

这里我获取了nickname半个月前这个代码没问题,现在运行报错TypeError: Cannot read properties of undefined (reading 'username')

groupTemp = groupTemp.field("user_id, name, content, images, publish_date").getTemp()  
let userTemp = db.collection("uni-id-users").field("_id,username,nickname,avatar_file").getTemp()  
db.collection(groupTemp, userTemp).orderBy("publish_date desc").skip(skip).limit(15).get().then(  
    res => {  

    }  
)

uni-id-users.schema.ext.js这个文件我没改过是自动生成的代码如下

// schema扩展相关文档请参阅:https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html  
const db = uniCloud.database();  
const dbCmd = db.command  
module.exports = {  
    trigger: {  
        async afterReadAsSecondaryCollection(e) {  
            await afterReadAction(e, true)  
        },  
        async afterRead(e) {  
            await afterReadAction(e)  
        }  
    }  
}  

async function afterReadAction({  
    field,  
    result,  
    userInfo: currentUserInfo  
} = {}, isGetTemp = false) {  
    if (result && field && field.includes("nickname")) {  
        //uni-im 处理查询nickname,但值为空的情况  
        let {  
            data  
        } = result  
        // 为联查 且为副表时的字段  
        if (isGetTemp && typeof(data[0]) == "object" && 'friend_uid' in data[0]) {  
            data = data.map(item => item.friend_uid[0])  
        }  

        // console.log('data',data);  
        if (!Array.isArray(data)) {  
            data = [data]  
        }  
        // 记录没有nickname的用户id  
        let user_ids = [],  
            usersInfo = {};  
        data.forEach(item => {  
            if (item && !item.nickname) {  
                user_ids.push(item._id)  
            }  
        })  
        if (user_ids.length) {  
            console.info('注意:uni-im项目用户数据依赖nickname。有' + user_ids.length +  
                `个用户数据 nickname 的值为空,已多执行一次数据库查询:将此用户的“用户名”或“邮箱”或“手机号”脱敏后,作为nickname输出。请引导用户完善nickname,减少查库次数`)  
            let res = await db.collection('uni-id-users')  
                .where({  
                    _id: dbCmd.in(user_ids)  
                })  
                .field({  
                    username: true,  
                    email: true,  
                    mobile: true  
                })  
                .get()  
            usersInfo = res.data.reduce((sum, current) => {  
                sum[current._id] = current  
                return sum  
            }, {})  
        }  

        let isUniImAdmin = currentUserInfo.role.includes('uni-im-admin') || currentUserInfo.role.includes('admin')  

        data.forEach(item => {  
            if (!item.nickname) {  
                let userInfo = usersInfo[item._id]  
                // 管理员不更改  
                if (!isUniImAdmin) {  
                    item.nickname = hideUsernameStr(userInfo.username) || hideEmailStr(userInfo.email) ||  
                        hideMobileStr(userInfo.mobile)  
                }  
            }  

            // 特殊处理某个用户xxx  
            if (item._id == "xxx") {  
                item.nickname = "xxx"  
                item.avatar_file = {  
                    url: "xxx"  
                }  
            }  

        })  

        function hideUsernameStr(username) {  
            if (username == undefined) {  
                return false  
            }  
            let length = username.length  
            let n = parseInt(length / 2.5) * 2  
            return username.substr(0, length - n) + '**' + username.substr(-1 * n / 2)  
        }  

        function hideEmailStr(email) {  
            if (email == undefined) {  
                return false  
            }  
            const content = email.split("@")  
            return content[0].substr(0, content[0].length - 2) + '**' + content[1]  
        }  

        function hideMobileStr(mobile) {  
            if (mobile == undefined) {  
                return false  
            }  
            return mobile.substr(0, 3) + '****' + mobile.substr(-1 * 4)  
        }  
    }  
}

我在代码里面加了一句打印

async function afterReadAction({  
    field,  
    result,  
    userInfo: currentUserInfo  
} = {}, isGetTemp = false) {  
    if (result && field && field.includes("nickname")) {  
        //uni-im 处理查询nickname,但值为空的情况  
        let {  
            data  
        } = result  

        console.log(result)

打印结果如下 很显然uni-id-users表的结果被包在了关联表的user_id字段中所以uni-id-users.schema.ext.js之后的代码无法获取到username

{  
    "affectedDocs": 1,  
    "data": [{  
        "_id": "6491980bf43e6001c1fa5234",  
        "user_id": [{  
            "_id": "6478d13f0c801c6b9751c4bc",  
            "username": "admin",  
            "nickname": "admin5",  
            "avatar_file": {  
                "extname": "png",  
                "name": "6478d13f0c801c6b9751c4bc1686316933868",  
                "url": ""  
            }  
        }],  
        "name": "新团",  
        "content": "哈哈",  
        "images": [  
            ""  
        ],  
        "publish_date": 1687263242945  
    }  
}

我想难道是db.collection改规则了吗?前些天代码是没有任何问题的,前两天升级了一次HBuilderX

2023-07-12 15:12 负责人:DCloud_uniCloud_JSON 分享
已邀请:
DCloud_uniCloud_JSON

DCloud_uniCloud_JSON

不是升级HBuilderX引起的,是你之前下载了 uni-im 插件,包含了uni-id-users.schema.ext.js
这个文件是:当用户没有昵称,则自动获取使用脱敏(打*号)后的注册手机号/邮箱当昵称。
之前存在部分表联查不兼容的问题,最新版已经修复了此问题。

最新版:

// schema扩展相关文档请参阅:https://uniapp.dcloud.net.cn/uniCloud/jql-schema-ext.html  
const db = uniCloud.database();  
const dbCmd = db.command  
module.exports = {  
    trigger: {  
        async afterReadAsSecondaryCollection(e) {  
            await afterReadAction(e, true)  
        },  
        async afterRead(e) {  
            await afterReadAction(e)  
        }  
    }  
}  

async function afterReadAction({  
    field,  
    result,  
    userInfo: currentUserInfo,  
    primaryCollection  
} = {}, asSecondaryCollection = false) {  
    if (result && field && field.includes("nickname")) {  
        //uni-im 处理查询nickname,但值为空的情况  
        let {  
            data  
        } = result  

    if( !Array.isArray(data) ){  
      // 说明走了 getOne  
      data = [data]  
    }  

        // 为联查 且为副表时的字段  
        if (asSecondaryCollection && typeof(data[0]) == "object") {  
            let foreignKeysObj = {  
                "uni-im-group-member":"user_id",  
                "uni-im-friend":"friend_uid"  
            }  
            let foreignKey = foreignKeysObj[primaryCollection]  

            if(foreignKey in data[0]){  
                data = data.map(item => item[foreignKey][0])  
            }else{  
        return console.log('触发器uni-id-users.schema.ext.js,未在当前操作生效。如需应用此触发器,请补充:主表表名及其foreignKey的值,到触发器uni-id-users.schema.ext.js的变量foreignKeysObj内');  
            }  
        }  

        // console.log('data',data);  
        if (!Array.isArray(data)) {  
            data = [data]  
        }  
        // 记录没有nickname的用户id  
        let user_ids = [],  
            usersInfo = {};  
        data.forEach(item => {  
            if (item && !item.nickname) {  
                user_ids.push(item._id)  
            }  
        })  
        if (user_ids.length) {  
            console.info('注意:uni-im项目用户数据依赖nickname。有' + user_ids.length +  
                `个用户数据 nickname 的值为空,已多执行一次数据库查询:将此用户的“用户名”或“邮箱”或“手机号”脱敏后,作为nickname输出。请引导用户完善nickname,减少查库次数`)  
            let res = await db.collection('uni-id-users')  
                .where({  
                    _id: dbCmd.in(user_ids)  
                })  
                .field({  
                    username: true,  
                    email: true,  
                    mobile: true  
                })  
                .limit(1000)  
                .get()  
            usersInfo = res.data.reduce((sum, current) => {  
                sum[current._id] = current  
                return sum  
            }, {})  
        }  

        let isUniImAdmin = currentUserInfo.role.includes('uni-im-admin') || currentUserInfo.role.includes('admin')  

        data.forEach(item => {  
            if (!item.nickname) {  
                let userInfo = usersInfo[item._id]  
                // 管理员可以看到不打码的  
                if (isUniImAdmin) {  
                    item.nickname = userInfo.username || userInfo.email || userInfo.mobile  
                }else{  
                    item.nickname = hideUsernameStr(userInfo.username) || hideEmailStr(userInfo.email) ||  
                                            hideMobileStr(userInfo.mobile)  
                }  
            }else if(!isUniImAdmin && item.nickname.includes('@')){  
                // 禁止昵称用邮箱 脱敏处理  
                item.nickname = hideEmailStr(item.nickname)  
            }  

            // 特殊处理某个用户xxx  
            if (item._id == "xxx") {  
                item.nickname = "xxx"  
                item.avatar_file = {  
                    url: "xxx"  
                }  
            }  

        })  

        function hideUsernameStr(username) {  
            if (username == undefined) {  
                return false  
            }  
            let length = username.length  
            let n = parseInt(length / 2.5) * 2  
            return username.substr(0, length - n) + '**' + username.substr(-1 * n / 2)  
        }  

        function hideEmailStr(email) {  
            if (email == undefined) {  
                return false  
            }  
            const content = email.split("@")  
            return content[0].substr(0, content[0].length - 2) + '**' + content[1]  
        }  

        function hideMobileStr(mobile) {  
            if (mobile == undefined) {  
                return false  
            }  
            return mobile.substr(0, 3) + '****' + mobile.substr(-1 * 4)  
        }  
    }  
}

要回复问题请先登录注册