在 Objection.js 中,如何在查询中包含虚拟列?
In Objection.js, how can I include a virtual column with my query?
我想创建一个 expired_bool
虚拟列。
我有以下 3 个 tables:
订阅:
id
duration
price
1
30
0.99
2
360
1.99
发票:
id
user_id
purchase_date
1
34
2020-01-01 01:21:01
2
42
2021-02-19 19:19:19
invoice_items:
id
user_id
invoice_id
subscription_id
activation_date
1
34
1
1
2020-05-15 12:51:51
2
34
1
2
2021-02-20 20:20:12
3
42
2
1
NULL
4
42
2
2
2021-02-20 20:20:12
这就是 User
、Invoice
和 InvoiceItems
table 在 Objection.js 中的建模方式:
class User extends Model {
static get tableName() {
return "users";
}
static get relationMappings() {
return {
invoices: {
relation: Model.HasManyRelation,
modelClass: Invoice,
join: {
from: "users.id",
to: "invoices.user_id",
},
},
invoiceItems: {
relation: Model.HasManyRelation,
modelClass: InvoiceItem,
join: {
from: "users.id",
to: "invoice_items.user_id",
},
},
};
}
}
class Invoice extends Model {
static get tableName() {
return "invoices";
}
static get relationMappings() {
return {
user: {
relation: Model.BelongsToOneRelation,
modelClass: User,
join: {
from: "invoices.user_id",
to: "users.id",
},
},
invoiceItems: {
relation: Model.HasManyRelation,
modelClass: InvoiceItem,
join: {
from: "invoices.id",
to: "invoice_items.invoice_id",
},
},
};
}
}
class InvoiceItem extends Model {
static get tableName() {
return "invoice_items";
}
static get relationMappings() {
return {
invoice: {
relation: Model.BelongsToOneRelation,
modelClass: Invoice,
join: {
from: "invoice_items.invoice_id",
to: "invoice.id",
},
},
user: {
relation: Model.BelongsToOneRelation,
modelClass: User,
join: {
from: "invoice_items.user_id",
to: "users.id",
},
},
subscription: {
relation: Model.HasOneRelation,
modelClass: Subscription,
join: {
from: "invoice_items.subscription_id",
to: "subscriptions.id",
},
},
};
}
}
这就是我 查询 用户和 his/her 购买的方式:
async function getUserAllWithPasswordByIdAsync(userId) {
try {
const query = await User.query()
.findById(userId)
.withGraphFetched("invoiceItems.subscription")
.withGraphFetched("invoices")
return query;
}
catch (error) {
console.log(error)
}
}
顺便说一句,expired_bool
虚拟列是通过检查 invoiceItems 的 activation date
并从中添加 duration
来确定的订阅 table,并确保该日期是今天的未来日期。
所以总而言之,我如何确定 invoiceItem
是否自动过期(通过使用虚拟列,应将其添加到 invoiceItems
table),以及确保这包含在我的 User
?
查询中
一种可能的解决方案是将 expiry_date
列添加到 invoice_items
。
activation_date
和 expiry_date
都将在订阅激活期间设置
activation_date = today's date
expiry_date = activation_date + subscription duration
invoice_items:
id
user_id
invoice_id
subscription_id
activation_date
expiry_date
1
34
1
1
2020-05-15 12:51:51
2020-06-14 12:51:51
2
34
1
2
2021-02-20 20:20:12
2022-02-15 20:20:12
3
42
2
1
NULL
NULL
4
42
2
2
2021-02-20 20:20:12
2022-02-15 20:20:12
查询活动 invoice_items 将像
一样简单
select "invoice_items".* from "invoice_items"
where "invoice_items"."expiry_date" >= [today's date]
假设现有订阅永远不会改变(并且只添加具有新 subscription_id
的新订阅),这种方法应该有效。
显然,您不能使用虚拟字段进行异步操作。也不能基于虚拟字段查询。它们完全在 javascript.
中定义
所以可以按如下方式完成(使用从Objection.js导入的raw
):
import objection from "objection";
const { Model, raw } = objection;
...
class InvoiceItem extends Model {
...
static modifiers = {
expiryInfo(qb) {
qb.select(
'invoice_items.*',
raw('activation_date + make_interval(days => subscription.duration)').as('expiration_date'),
raw('activation_date + make_interval(days => subscription.duration) < now()').as('expired_bool'),
).joinRelated('subscription')
}
}
...
}
const query = await User.query()
.findById(userId)
.withGraphFetched("invoiceItems(expiryInfo).subscription")
.withGraphFetched("invoices")
这使用了 Postgres 函数,但对于其他数据库,思路仍然相同,尽管 raw
中的代码可能需要稍作调整。
我想创建一个 expired_bool
虚拟列。
我有以下 3 个 tables:
订阅:
id | duration | price |
---|---|---|
1 | 30 | 0.99 |
2 | 360 | 1.99 |
发票:
id | user_id | purchase_date |
---|---|---|
1 | 34 | 2020-01-01 01:21:01 |
2 | 42 | 2021-02-19 19:19:19 |
invoice_items:
id | user_id | invoice_id | subscription_id | activation_date |
---|---|---|---|---|
1 | 34 | 1 | 1 | 2020-05-15 12:51:51 |
2 | 34 | 1 | 2 | 2021-02-20 20:20:12 |
3 | 42 | 2 | 1 | NULL |
4 | 42 | 2 | 2 | 2021-02-20 20:20:12 |
这就是 User
、Invoice
和 InvoiceItems
table 在 Objection.js 中的建模方式:
class User extends Model {
static get tableName() {
return "users";
}
static get relationMappings() {
return {
invoices: {
relation: Model.HasManyRelation,
modelClass: Invoice,
join: {
from: "users.id",
to: "invoices.user_id",
},
},
invoiceItems: {
relation: Model.HasManyRelation,
modelClass: InvoiceItem,
join: {
from: "users.id",
to: "invoice_items.user_id",
},
},
};
}
}
class Invoice extends Model {
static get tableName() {
return "invoices";
}
static get relationMappings() {
return {
user: {
relation: Model.BelongsToOneRelation,
modelClass: User,
join: {
from: "invoices.user_id",
to: "users.id",
},
},
invoiceItems: {
relation: Model.HasManyRelation,
modelClass: InvoiceItem,
join: {
from: "invoices.id",
to: "invoice_items.invoice_id",
},
},
};
}
}
class InvoiceItem extends Model {
static get tableName() {
return "invoice_items";
}
static get relationMappings() {
return {
invoice: {
relation: Model.BelongsToOneRelation,
modelClass: Invoice,
join: {
from: "invoice_items.invoice_id",
to: "invoice.id",
},
},
user: {
relation: Model.BelongsToOneRelation,
modelClass: User,
join: {
from: "invoice_items.user_id",
to: "users.id",
},
},
subscription: {
relation: Model.HasOneRelation,
modelClass: Subscription,
join: {
from: "invoice_items.subscription_id",
to: "subscriptions.id",
},
},
};
}
}
这就是我 查询 用户和 his/her 购买的方式:
async function getUserAllWithPasswordByIdAsync(userId) {
try {
const query = await User.query()
.findById(userId)
.withGraphFetched("invoiceItems.subscription")
.withGraphFetched("invoices")
return query;
}
catch (error) {
console.log(error)
}
}
顺便说一句,expired_bool
虚拟列是通过检查 invoiceItems 的 activation date
并从中添加 duration
来确定的订阅 table,并确保该日期是今天的未来日期。
所以总而言之,我如何确定 invoiceItem
是否自动过期(通过使用虚拟列,应将其添加到 invoiceItems
table),以及确保这包含在我的 User
?
一种可能的解决方案是将 expiry_date
列添加到 invoice_items
。
activation_date
和 expiry_date
都将在订阅激活期间设置
activation_date = today's date
expiry_date = activation_date + subscription duration
invoice_items:
id | user_id | invoice_id | subscription_id | activation_date | expiry_date |
---|---|---|---|---|---|
1 | 34 | 1 | 1 | 2020-05-15 12:51:51 | 2020-06-14 12:51:51 |
2 | 34 | 1 | 2 | 2021-02-20 20:20:12 | 2022-02-15 20:20:12 |
3 | 42 | 2 | 1 | NULL | NULL |
4 | 42 | 2 | 2 | 2021-02-20 20:20:12 | 2022-02-15 20:20:12 |
查询活动 invoice_items 将像
一样简单select "invoice_items".* from "invoice_items"
where "invoice_items"."expiry_date" >= [today's date]
假设现有订阅永远不会改变(并且只添加具有新 subscription_id
的新订阅),这种方法应该有效。
显然,您不能使用虚拟字段进行异步操作。也不能基于虚拟字段查询。它们完全在 javascript.
中定义所以可以按如下方式完成(使用从Objection.js导入的raw
):
import objection from "objection";
const { Model, raw } = objection;
...
class InvoiceItem extends Model {
...
static modifiers = {
expiryInfo(qb) {
qb.select(
'invoice_items.*',
raw('activation_date + make_interval(days => subscription.duration)').as('expiration_date'),
raw('activation_date + make_interval(days => subscription.duration) < now()').as('expired_bool'),
).joinRelated('subscription')
}
}
...
}
const query = await User.query()
.findById(userId)
.withGraphFetched("invoiceItems(expiryInfo).subscription")
.withGraphFetched("invoices")
这使用了 Postgres 函数,但对于其他数据库,思路仍然相同,尽管 raw
中的代码可能需要稍作调整。