uni-app 联表查询中临时表使用skip后无法正确匹配关联数据

uni-app 联表查询中临时表使用skip后无法正确匹配关联数据

操作步骤:

如上

预期结果:

如上

实际结果:

如上

bug描述:

order 表数据:

[
    {
        "_id": "order_1001",
        "user_id": "user_002", // 指向user表的_id值为user_002的数据  
        "product_name": "无线耳机",
    },
    {
        "_id": "order_1002",
        "user_id": "user_002", // 指向user表的_id值为user_002的数据   
        "product_name": "机械键盘",
    },
    {
        "_id": "order_2001",
        "user_id": "user_001", // 指向user表的_id值为user_001的数据   
        "product_name": "智能手表",
    }
]

order 表结构:

{
    "bsonType": "object",
    "description": "订单副表",
    "required": ["product_name", "user_id"],
    "permission": {
        "read": true,
        "create": true,
        "update": true,
        "delete": true
    },
    "properties": {
        "_id": {
            "description": "订单ID"
        },
        "user_id": {
            "bsonType": "string",
            "foreignKey": "user._id", // 指向 user 表的 _id  
            "description": "关联的用户ID"
        },
        "product_name": {
            "bsonType": "string",
            "description": "商品名称",
        },
    }
}

user 表数据:

[
    {
        "_id": "user_001",
        "username": "张三",
    },
    {
        "_id": "user_002",
        "username": "李四",
    },
    {
        "_id": "user_003",
        "username": "王五",
    }
]

user 表结构:

{
    "bsonType": "object",
    "description": "用户主表",
    "required": ["username"],
    "permission": {
        "read": true,
        "create": true,
        "update": true,
        "delete": true
    },
    "properties": {
        "_id": {
            "description": "用户唯一ID"
        },
        "username": {
            "bsonType": "string",
            "description": "用户名",
        },
    }
}

联表查询代码:

const db = uniCloud.database()

const order = db.collection('order').getTemp()
const user = db.collection('user').skip(1).getTemp() // 跳过了user表的第一条数据
async function demo() {
    const res = await db.collection(order, user).get()
    console.log(res)
}
demo()

通过 skip(1) 跳过了 user 表的第一条数据,此时 user 表应该还剩两条数据:

{
    "_id": "user_002",
    "username": "李四",
},
{
    "_id": "user_003",
    "username": "王五",
}

理论上的打印值:

[
    {
        "_id": "order_1001",
        "user_id": [{
            "_id": "user_002",
            "username": "李四",
        }], // 指向user表的_id值为user_002的数据   
        "product_name": "无线耳机"
    },
    {
        "_id": "order_1002",
        "user_id": [{
            "_id": "user_002",
            "username": "李四",
        }], // 指向user表的_id值为user_002的数据   
        "product_name": "机械键盘"
    },
    {
        "_id": "order_2001",
        "user_id": [], // 指向user表的_id值为user_001的数据,但是user_001的数据被skip(1)跳过了,所以没有
        "product_name": "智能手表"
    }
]

上传的图1

修改为 limit(1) 后的代码:

const db = uniCloud.database()

const order = db.collection('order').getTemp()
const user = db.collection('user').limit(1).getTemp() // 从skip(1)修改为limit(1)
async function demo() {
    const res = await db.collection(order, user).get()
    console.log(res)
}
demo()

修改后的结果


更多关于uni-app 联表查询中临时表使用skip后无法正确匹配关联数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

副表查询是有条件的 order.user_id==user._id,然后才会 skip 和 limit。
副表查询伪代码如下: db.collection(“user”).where({_id: “order.user_id”}).skip(1).get()

更多关于uni-app 联表查询中临时表使用skip后无法正确匹配关联数据的实战教程也可以访问 https://www.itying.com/category-93-b0.html


GitHub上的issues是你发的吗?我已经回复了,或者你就在这个帖子下回复我,不要两边都发。

github上的issue是我发的,这个帖子我就关闭了吧,在github上询问你

有时间看一下github上的issue…我还有一点疑问,万分感谢Thanks♪(・ω・)ノ

回复 1***@qq.com: 已回复。

在uni-app的联表查询中,对临时表使用skip()方法确实会导致关联数据匹配异常。这是因为联表查询的关联逻辑是在数据库层面执行的,而skip()操作会改变临时表的数据集,从而影响关联匹配。

从你的测试结果可以看出:

  1. 使用skip(1)后,虽然user表跳过了第一条数据,但order表中user_iduser_001的记录仍然能够关联到被跳过的用户数据
  2. 改为limit(1)后,结果同样不符合预期

这是因为临时表的skip()limit()操作实际上是在联表查询完成之后应用的,而不是在关联匹配之前。数据库会先完成所有数据的关联,然后再应用这些过滤条件。

正确的解决方案: 在联表查询中,应该使用where条件来过滤关联表的数据,而不是使用skip()

const db = uniCloud.database()

const order = db.collection('order').getTemp()
const user = db.collection('user').where({
  '_id': db.command.neq('user_001') // 使用where条件排除特定用户
}).getTemp()

async function demo() {
    const res = await db.collection(order, user).get()
    console.log(res)
}
demo()

或者,如果需要在联表查询后进行分页,应该在最终查询结果上使用skip()

const db = uniCloud.database()

const order = db.collection('order').getTemp()
const user = db.collection('user').getTemp()

async function demo() {
    const res = await db.collection(order, user).skip(1).get() // 在最终结果上skip
    console.log(res)
}
demo()
回到顶部