Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_36567140
unidocs-zh
提交
e44f75e2
U
unidocs-zh
项目概览
qq_36567140
/
unidocs-zh
与 Fork 源项目一致
Fork自
DCloud / unidocs-zh
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e44f75e2
编写于
1月 11, 2022
作者:
雪洛
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
docs: uniCloud jql
上级
03a6644a
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
224 addition
and
211 deletion
+224
-211
docs/uniCloud/jql.md
docs/uniCloud/jql.md
+224
-211
未找到文件。
docs/uniCloud/jql.md
浏览文件 @
e44f75e2
...
...
@@ -363,6 +363,11 @@ const res = await db.collection('goods').where(`${new RegExp(searchVal, 'i')}.te
### 联表查询@lookup
为方便文档描述定义以下两个概念:
临时表:getTemp方法返回的结果,例:
`const article = db.collection('article').getTemp() `
,此处 article 就是一个临时表
虚拟表:主表与副表联表产生的表,例:
`db.collection(article, 'comment').get()`
> JQL于2021年4月28日优化了联表查询策略,详情参考:[联表查询策略调整](https://ask.dcloud.net.cn/article/38966)
`JQL`
提供了更简单的联表查询方案。不需要学习join、lookup等复杂方法。
...
...
@@ -372,10 +377,10 @@ const res = await db.collection('goods').where(`${new RegExp(searchVal, 'i')}.te
JQL联表查询有以下两种写法:
```
js
// 直接关联多个表为虚拟表再进行查询
// 直接关联多个表为虚拟表再进行查询
,旧写法,目前更推荐使用getTemp进行联表查询
const
res
=
await
db
.
collection
(
'
order,book
'
).
where
(
'
_id=="1"
'
).
get
()
// 直接关联order和book之后再过滤
// 使用getTemp先过滤处理获取临时表再联表查询
// 使用getTemp先过滤处理获取临时表再联表查询
,推荐用法
const
order
=
db
.
collection
(
'
order
'
).
where
(
'
_id=="1"
'
).
getTemp
()
// 注意结尾的方法是getTemp,对order表过滤得到临时表
const
res
=
await
db
.
collection
(
order
,
'
book
'
).
get
()
// 将获取的order表的临时表和book表进行联表查询
```
...
...
@@ -520,9 +525,10 @@ schema保存后,即使用JQL查询。查询表设为order和book这2个表名
```
js
// 客户端联表查询
const
db
=
uniCloud
.
database
()
db
.
collection
(
'
order,book
'
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
const
order
=
db
.
collection
(
'
order
'
).
field
(
'
book_id,quantity
'
).
getTemp
()
// 临时表field方法内需要包含关联字段,否则无法建立关联关系
const
book
=
db
.
collection
(
'
book
'
).
field
(
'
_id,title,author
'
).
getTemp
()
// 临时表field方法内需要包含关联字段,否则无法建立关联关系
db
.
collection
(
order
,
book
)
// 注意collection方法内需要传入所有用到的表名,用逗号分隔,主表需要放在第一位
.
where
(
'
book_id.title == "三国演义"
'
)
// 查询order表内书名为“三国演义”的订单
.
field
(
'
book_id{title,author},quantity
'
)
// 这里联表查询book表返回book表内的title、book表内的author、order表内的quantity
.
get
()
.
then
(
res
=>
{
console
.
log
(
res
);
...
...
@@ -639,6 +645,145 @@ db.collection('order,book').get()
-
上述示例中如果order表的
`book_id`
字段是数组形式存放多个book_id,也跟上述写法一致,JQL会自动根据字段类型进行联表查询
-
各个表的_id字段会默认带上,即使没有指定返回
#### 临时表联表查询@lookup-with-temp
> 新增于`HBuilderX 3.2.6`
在此之前JQL联表查询只能直接使用虚拟表,而不能先对主表、副表过滤再生成虚拟表。由于生成虚拟表时需要整个主表和副表进行联表,在数据量大的情况下性能会很差。
使用临时表进行联表查询,可以先对主表或者副表进行过滤,然后在处理后的临时表的基础上生成虚拟表。
仍以上面article、comment两个表为例
获取article_id为'1'的文章及其评论的数据库操作,在直接联表查询和使用临时表联表查询时写法分别如下
```
js
// 直接使用虚拟表查询
const
res
=
await
db
.
collection
(
'
article,comment
'
)
.
where
(
'
article_id._value=="1"
'
)
.
get
()
// 先过滤article表,再获取虚拟表联表获取评论
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id=="1"
'
).
getTemp
()
// 注意是getTemp不是get
const
res
=
await
db
.
collection
(
article
,
'
comment
'
).
get
()
```
直接使用虚拟表联表查询,在第一步生成虚拟表时会以主表所有数据和副表进行联表查询,如果主表数据量很大,这一步会浪费相当多的时间。先过滤主表则没有这个问题,过滤之后仅有一条数据和副表进行联表查询。
**临时表内可以使用如下方法**
> 方法调用必须严格按照顺序,比如field不能放在where之前
```
js
where
field
// 关于field的使用限制见下方说明
orderBy
skip
limit
```
```
js
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id=="1"
'
).
field
(
'
title
'
).
getTemp
()
// 此处过滤article表,仅保留title字段。会导致下一步查询时找不到关联关系而查询失败
const
res
=
await
db
.
collection
(
article
,
'
comment
'
).
get
()
```
**组合出来的虚拟表查询时可以使用的方法**
> 方法调用必须严格按照顺序,比如foreignKey不能放在where之后
```
js
foreignKey
// foreignKey自 HBuilderX 3.3.7版本支持
where
field
// 关于field的使用限制见下方说明
orderBy
skip
limit
```
一般情况下不需要再对虚拟表额外处理,因为数据在临时表内已经进行了过滤排序等操作。以下代码仅供演示,并无实际意义
```
js
const
article
=
db
.
collection
(
'
article
'
).
getTemp
()
const
comment
=
db
.
collection
(
'
comment
'
).
getTemp
()
const
res
=
await
db
.
collection
(
article
,
comment
).
orderBy
(
'
title desc
'
).
get
()
// 按照title倒序排列
```
**field使用限制**
-
`HBuilderX 3.3.7`
之前 field 内仅可以进行字段过滤,不可对字段重命名、进行运算,
`field('name as value')`
、
`field('add(score1, score2) as totalScore')`
都是不支持的用法
-
`HBuilderX 3.3.7`
及以上版本支持对字段重命名或运算
-
进行联表查询时仅能使用临时表内已经过滤的字段间的关联关系,例如上面article、comment的查询,如果换成以下写法就无法联表查询
-
不建议在虚拟表内再对副表字段重命名或者运算,如果有此类需求应在临时表内进行,会出现预期之外的结果,
**为兼容旧版此用法仅输出警告不会抛出错误**
**权限校验**
要求组成虚拟表的各个临时表都要满足权限限制,即权限校验不会计算组合成虚拟表之后使用的where、field
以下为一个订单表(order)和书籍表(book)的schema示例
```
js
// order schema
{
"
bsonType
"
:
"
object
"
,
"
required
"
:
[],
"
permission
"
:
{
"
read
"
:
"
doc.uid==auth.uid
"
,
"
create
"
:
false
,
"
update
"
:
false
,
"
delete
"
:
false
},
"
properties
"
:
{
"
id
"
:
{
// 订单id
"
bsonType
"
:
"
string
"
},
"
book_id
"
:
{
// 书籍id
"
bsonType
"
:
"
string
"
},
"
uid
"
:
{
// 用户id
"
bsonType
"
:
"
string
"
}
}
}
// book schema
{
"
bsonType
"
:
"
object
"
,
"
required
"
:
[],
"
permission
"
:
{
"
read
"
:
true
,
"
create
"
:
false
,
"
update
"
:
false
,
"
delete
"
:
false
},
"
properties
"
:
{
"
id
"
:
{
// 书籍id
"
bsonType
"
:
"
string
"
},
"
name
"
:
{
// 书籍名称
"
bsonType
"
:
"
string
"
}
}
}
```
如果先对主表进行过滤
`where('uid==$cloudEnv_uid')`
,则能满足权限限制(
`order表的"doc.uid==auth.uid"`
)
```
js
const
order
=
db
.
collection
(
'
order
'
)
.
where
(
'
uid==$cloudEnv_uid
'
)
// 先过滤order表内满足条件的部分
.
getTemp
()
const
res
=
await
db
.
collection
(
order
,
'
book
'
).
get
()
// 可以通过权限校验
```
如果不对主表过滤,而是对虚拟表(联表结果)进行过滤,则无法满足权限限制(
`order表的"doc.uid==auth.uid"`
)
```
js
const
order
=
db
.
collection
(
'
order
'
).
getTemp
()
const
res
=
await
db
.
collection
(
order
,
'
book
'
).
where
(
'
uid==$cloudEnv_uid
'
).
get
()
// 对虚拟表过滤,无法通过权限校验
```
#### 设置字段别名@lookup-field-alias
联表查询时也可以在field内对字段进行重命名,写法和简单查询时别名写法类似,
`原字段名 as 新字段名`
即可。
[
简单查询时的字段别名
](
uniCloud/jql.md?id=alias
)
...
...
@@ -648,9 +793,11 @@ db.collection('order,book').get()
```
js
// 客户端联表查询
const
db
=
uniCloud
.
database
()
db
.
collection
(
'
order,book
'
)
.
where
(
'
book_id.title == "三国演义"
'
)
.
field
(
'
book_id{title as book_title,author as book_author},quantity as order_quantity
'
)
const
order
=
db
.
collection
(
'
order
'
).
field
(
'
book_id,quantity
'
).
getTemp
()
const
book
=
db
.
collection
(
'
book
'
).
field
(
'
_id,title as book_title,author as book_author
'
).
getTemp
()
db
.
collection
(
order
,
book
)
.
where
(
'
book_id.book_title == "三国演义"
'
)
// 如果field内对副表字段title进行了重命名,where方法内则需要使用重命名之后的字段名
.
get
()
.
then
(
res
=>
{
console
.
log
(
res
);
...
...
@@ -689,56 +836,6 @@ db.collection('order,book')
> 2021年4月28日10点前此方法仅用于兼容JQL联表查询策略调整前后的写法,在此日期后更新的clientDB(上传schema、uni-id均会触发更新)才会有指定foreignKey的功能,关于此次调整请参考:[联表查询策略调整](https://ask.dcloud.net.cn/article/38966)
```
js
db
.
collection
(
'
comment,user
'
)
.
where
(
'
comment_id=="1-1"
'
)
.
field
(
'
content,sender,receiver.name
'
)
.
foreignKey
(
'
comment.receiver
'
)
// 仅使用comment表内receiver字段下的foreignKey进行主表和副表之间的关联
.
get
()
```
#### 副表foreignKey联查@st-foreign-key
`2021年4月28日`
之前的JQL只支持主表的foreignKey,把副表内容嵌入主表的foreignKey字段下面。不支持处理副本的foreignKey。
`2021年4月28日`
调整后,新版支持副表foreignKey联查。副表的数据以数组的方式嵌入到主表中作为一个虚拟表使用。
**关联查询后的数据结构如下:**
> 通过HBuilderX提供的[JQL数据库管理](uniCloud/jql-runner.md)功能方便的查看联表查询时的虚拟表结构
主表某字段foreignKey指向副表时
```
js
{
"
主表字段名1
"
:
"
xxx
"
,
"
主表字段名2
"
:
"
xxx
"
,
"
主表内foreignKey指向副表的字段名
"
:
[{
"
副表字段名1
"
:
"
xxx
"
,
"
副表字段名2
"
:
"
xxx
"
,
}]
}
```
副表某字段foreignKey指向主表时
```
js
{
"
主表字段名1
"
:
"
xxx
"
,
"
主表字段名2
"
:
"
xxx
"
,
"
副表foreignKey指向的主表字段名
"
:
{
"
副表1表名
"
:
[{
// 一个主表字段可能对应多个副表字段的foreignKey
"
副表1字段名1
"
:
"
xxx
"
,
"
副表1字段名2
"
:
"
xxx
"
,
}],
"
副表2表名
"
:
[{
// 一个主表字段可能对应多个副表字段的foreignKey
"
副表2字段名1
"
:
"
xxx
"
,
"
副表2字段名2
"
:
"
xxx
"
,
}],
"
_value
"
:
"
主表字段原始值
"
// 使用副表foreignKey查询时会在关联的主表字段内以_value存储该字段的原始值,新增于HBuilderX 3.1.16-alpha
}
}
```
例:
...
...
@@ -861,11 +958,67 @@ db.collection('comment,user')
}
```
```
js
const
comment
=
db
.
collection
(
'
comment
'
).
where
(
'
comment_id == "1-1"
'
).
getTemp
()
const
user
=
db
.
collection
(
'
user
'
).
field
(
'
uid,name
'
).
getTemp
()
db
.
collection
(
comment
,
user
)
.
foreignKey
(
'
comment.receiver
'
)
// 仅使用comment表内receiver字段下的foreignKey进行主表和副表之间的关联
.
get
()
```
**注意**
-
`HBuilderX 3.3.7`
及以上版本支持使用getTemp的虚拟表内使用foreignKey方法
#### 副表foreignKey联查@st-foreign-key
`2021年4月28日`
之前的JQL只支持主表的foreignKey,把副表内容嵌入主表的foreignKey字段下面。不支持处理副本的foreignKey。
`2021年4月28日`
调整后,新版支持副表foreignKey联查。副表的数据以数组的方式嵌入到主表中作为一个虚拟表使用。
**关联查询后的数据结构如下:**
> 通过HBuilderX提供的[JQL数据库管理](uniCloud/jql-runner.md)功能方便的查看联表查询时的虚拟表结构
主表某字段foreignKey指向副表时
```
js
{
"
主表字段名1
"
:
"
xxx
"
,
"
主表字段名2
"
:
"
xxx
"
,
"
主表内foreignKey指向副表的字段名
"
:
[{
"
副表字段名1
"
:
"
xxx
"
,
"
副表字段名2
"
:
"
xxx
"
,
}]
}
```
副表某字段foreignKey指向主表时
```
js
{
"
主表字段名1
"
:
"
xxx
"
,
"
主表字段名2
"
:
"
xxx
"
,
"
副表foreignKey指向的主表字段名
"
:
{
"
副表1表名
"
:
[{
// 一个主表字段可能对应多个副表字段的foreignKey
"
副表1字段名1
"
:
"
xxx
"
,
"
副表1字段名2
"
:
"
xxx
"
,
}],
"
副表2表名
"
:
[{
// 一个主表字段可能对应多个副表字段的foreignKey
"
副表2字段名1
"
:
"
xxx
"
,
"
副表2字段名2
"
:
"
xxx
"
,
}],
"
_value
"
:
"
主表字段原始值
"
// 使用副表foreignKey查询时会在关联的主表字段内以_value存储该字段的原始值,新增于HBuilderX 3.1.16-alpha
}
}
```
以下查询使用comment表的article字段对应的foreignKey进行关联查询
```
js
db
.
collection
(
'
article,comment
'
)
.
where
(
'
article_id._value=="1"
'
)
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id == "1"
'
).
getTemp
()
const
comment
=
db
.
collection
(
'
comment
'
).
getTemp
()
db
.
collection
(
article
,
comment
)
.
field
(
'
content,article_id
'
)
.
get
()
```
...
...
@@ -899,19 +1052,20 @@ db.collection('article,comment')
```
js
// 过滤副表字段
db
.
collection
(
'
article,comment
'
)
.
where
(
'
article_id._value=="1"
'
)
.
field
(
'
content,article_id{comment{content}}
'
)
.
get
()
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id == "1"
'
).
getTemp
()
const
comment
=
db
.
collection
(
'
comment
'
).
field
(
'
article,content
'
).
getTemp
()
// 如果有field方法,field内需包含关联字段以建立关联关系
db
.
collection
(
'
article,comment
'
).
get
()
// 查询结果如下
[{
"
content
"
:
"
content1
"
,
"
article_id
"
:
{
"
comment
"
:
[{
// 使用副表foreignKey联查时此处会自动插入一层副表表名
"
article
"
:
"
1
"
,
"
content
"
:
"
comment1-1
"
},
{
"
article
"
:
"
1
"
,
"
content
"
:
"
comment1-2
"
}],
"
_value
"
:
"
1
"
...
...
@@ -922,171 +1076,30 @@ db.collection('article,comment')
副表内的字段也可以使用
`as`
进行重命名,例如上述查询中如果希望将副表的content重命名为value可以使用如下写法
> HBuilderX 3.3.7及以上版本支持getTemp内使用as
```
js
// 重命名副表字段
db
.
collection
(
'
article,comment
'
)
.
where
(
'
article_id._value=="1"
'
)
.
field
(
'
content,article_id{comment{content as value}}
'
)
.
get
()
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id == "1"
'
).
getTemp
()
const
comment
=
db
.
collection
(
'
comment
'
).
field
(
'
article,content as value
'
).
getTemp
()
// 如果有field方法,field内需包含关联字段以建立关联关系
db
.
collection
(
article
,
comment
).
get
()
// 查询结果如下
[{
"
content
"
:
"
content1
"
,
"
article_id
"
:
{
"
comment
"
:
[{
// 使用副本foreignKey联查时此处会自动插入一层副表表名
"
article
"
:
"
1
"
,
"
value
"
:
"
comment1-1
"
},
{
"
article
"
:
"
1
"
,
"
value
"
:
"
comment1-2
"
}]
}
}]
```
#### 临时表联表查询@lookup-with-temp
> 新增于`HBuilderX 3.2.6`
为方便文档描述定义以下两个概念:
临时表:getTemp方法返回的结果,例:
`const article = db.collection('article').getTemp() `
,此处 article 就是一个临时表
虚拟表:主表与副表联表产生的表,例:
`db.collection(article, 'comment').get()`
在此之前JQL联表查询只能直接使用虚拟表,而不能先对主表、副表过滤再生成虚拟表。由于生成虚拟表时需要整个主表和副表进行联表,在数据量大的情况下性能会很差。
使用临时表进行联表查询,可以先对主表或者副表进行过滤,然后在处理后的临时表的基础上生成虚拟表。
仍以上面article、comment两个表为例
获取article_id为'1'的文章及其评论的数据库操作,在直接联表查询和使用临时表联表查询时写法分别如下
```
js
// 直接使用虚拟表查询
const
res
=
await
db
.
collection
(
'
article,comment
'
)
.
where
(
'
article_id._value=="1"
'
)
.
get
()
// 先过滤article表,再获取虚拟表联表获取评论
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id=="1"
'
).
getTemp
()
// 注意是getTemp不是get
const
res
=
await
db
.
collection
(
article
,
'
comment
'
).
get
()
```
直接使用虚拟表联表查询,在第一步生成虚拟表时会以主表所有数据和副表进行联表查询,如果主表数据量很大,这一步会浪费相当多的时间。先过滤主表则没有这个问题,过滤之后仅有一条数据和副表进行联表查询。
**临时表内可以使用如下方法**
> 方法调用必须严格按照顺序,比如field不能放在where之前
```
js
where
field
// 关于field的使用限制见下方说明
orderBy
skip
limit
```
```
js
const
article
=
db
.
collection
(
'
article
'
).
where
(
'
article_id=="1"
'
).
field
(
'
title
'
).
getTemp
()
// 此处过滤article表,仅保留title字段。会导致下一步查询时找不到关联关系而查询失败
const
res
=
await
db
.
collection
(
article
,
'
comment
'
).
get
()
```
**组合出来的虚拟表查询时可以使用的方法**
> 方法调用必须严格按照顺序,比如foreignKey不能放在where之后
```
js
foreignKey
// foreignKey自 HBuilderX 3.3.7版本支持
where
field
// 关于field的使用限制见下方说明
orderBy
skip
limit
```
一般情况下不需要再对虚拟表额外处理,因为数据在临时表内已经进行了过滤排序等操作。以下代码仅供演示,并无实际意义
```
js
const
article
=
db
.
collection
(
'
article
'
).
getTemp
()
const
comment
=
db
.
collection
(
'
comment
'
).
getTemp
()
const
res
=
await
db
.
collection
(
article
,
comment
).
orderBy
(
'
title desc
'
).
get
()
// 按照title倒序排列
```
**field使用限制**
-
`HBuilderX 3.3.7`
之前 field 内仅可以进行字段过滤,不可对字段重命名、进行运算,
`field('name as value')`
、
`field('add(score1, score2) as totalScore')`
都是不支持的用法
-
`HBuilderX 3.3.7`
及以上版本支持对字段重命名或运算
-
进行联表查询时仅能使用临时表内已经过滤的字段间的关联关系,例如上面article、comment的查询,如果换成以下写法就无法联表查询
-
不建议在虚拟表内再对副表字段重命名或者运算,如果有此类需求应在临时表内进行,会出现预期之外的结果,
**为兼容旧版此用法仅输出警告不会抛出错误**
**权限校验**
要求组成虚拟表的各个临时表都要满足权限限制,即权限校验不会计算组合成虚拟表之后使用的where、field
以下为一个订单表(order)和书籍表(book)的schema示例
```
js
// order schema
{
"
bsonType
"
:
"
object
"
,
"
required
"
:
[],
"
permission
"
:
{
"
read
"
:
"
doc.uid==auth.uid
"
,
"
create
"
:
false
,
"
update
"
:
false
,
"
delete
"
:
false
},
"
properties
"
:
{
"
id
"
:
{
// 订单id
"
bsonType
"
:
"
string
"
},
"
book_id
"
:
{
// 书籍id
"
bsonType
"
:
"
string
"
},
"
uid
"
:
{
// 用户id
"
bsonType
"
:
"
string
"
}
}
}
// book schema
{
"
bsonType
"
:
"
object
"
,
"
required
"
:
[],
"
permission
"
:
{
"
read
"
:
true
,
"
create
"
:
false
,
"
update
"
:
false
,
"
delete
"
:
false
},
"
properties
"
:
{
"
id
"
:
{
// 书籍id
"
bsonType
"
:
"
string
"
},
"
name
"
:
{
// 书籍名称
"
bsonType
"
:
"
string
"
}
}
}
```
如果先对主表进行过滤
`where('uid==$cloudEnv_uid')`
,则能满足权限限制(
`order表的"doc.uid==auth.uid"`
)
```
js
const
order
=
db
.
collection
(
'
order
'
)
.
where
(
'
uid==$cloudEnv_uid
'
)
// 先过滤order表内满足条件的部分
.
getTemp
()
const
res
=
await
db
.
collection
(
order
,
'
book
'
).
get
()
// 可以通过权限校验
```
如果不对主表过滤,而是对虚拟表(联表结果)进行过滤,则无法满足权限限制(
`order表的"doc.uid==auth.uid"`
)
```
js
const
order
=
db
.
collection
(
'
order
'
).
getTemp
()
const
res
=
await
db
.
collection
(
order
,
'
book
'
).
where
(
'
uid==$cloudEnv_uid
'
).
get
()
// 对虚拟表过滤,无法通过权限校验
```
### 查询记录过滤where条件@where
> 代码块`dbget`
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录