我无法将此查询转换为jooq(它是更大查询的一部分)
想法是仅选择具有所有指定属性的产品
WITH "products" as (
SELECT
p.id,
(
SELECT coalesce(
array_agg(attrs),
ARRAY ['NO_RELATIONS']
)
FROM unnest(ARRAY [
tts.v,
ingredient.v,
variation.v
]) AS "attrs"
WHERE attrs IS NOT NULL
) AS "attributes"
FROM t_product p
LEFT JOIN LATERAL (SELECT 'PRODUCED' :: TEXT AS v
FROM t_tech_spech AS tts
WHERE tts.product_id = p.id
LIMIT 1) AS tts ON TRUE
LEFT JOIN LATERAL (SELECT 'INGREDIENT' :: TEXT AS v
FROM t_tech_spech_item AS ingredient
WHERE ingredient.product_id = p.id
LIMIT 1) AS ingredient ON TRUE
LEFT JOIN LATERAL (SELECT 'FOR_SALE' :: TEXT AS v
FROM t_product_variation AS variation
WHERE variation.catalog_product_id = p.id
LIMIT 1) AS variation ON TRUE
) SELECT id, "attributes"
FROM products
WHERE attributes @> ARRAY ['PRODUCED', 'INGREDIENT'];
我已经完成了大部分工作,没有问题
val tts =
dsl.select(inline("PRODUCED").cast(TEXT).`as`("value"))
.from(T_TECH_SPECH)
.where(T_TECH_SPECH.PRODUCT_ID.equal(product.ID))
.limit(1)
.asTable("tts")
val ingredient =
dsl.select(inline("INGREDIENT").cast(TEXT).`as`("value"))
.from(T_TECH_SPECH_ITEM)
.where(T_TECH_SPECH_ITEM.PRODUCT_ID.equal(product.ID))
.limit(1)
.asTable("ingredient")
val variation =
dsl.select(inline("FOR_SALE").cast(TEXT).`as`("value"))
.from(T_PRODUCT_VARIATION)
.where(T_PRODUCT_VARIATION.CATALOG_PRODUCT_ID.equal(product.ID))
.and(T_PRODUCT_VARIATION.IS_DELETED.eq(false))
.limit(1)
.asTable("variation")
val attributes =
dsl.select(coalesce(arrayAgg(field("attrs")), field(array("NO_RELATIONS"))))
.from(
unnest(
array(
field("tts.value"),
field("ingredient.value"),
field("variation.value")
)
).`as`("attrs")
)
.where(field("attrs").isNotNull).asField<Array<String>>("attributes")
dsl.with("products")
.`as`(
select(
product.ID,
field(attributes)
).from(product)
.leftJoin(lateral(tts)).on(trueCondition())
.leftJoin(lateral(ingredient)).on(trueCondition())
.leftJoin(lateral(variation)).on(trueCondition())
)
.with("products_filtered")
.`as`(
select(
product.ID,
field("products.attributes").`as`("attributes")
).from("products")
.join(product).on(product.ID.eq(field("products.id", UUID::class.java)))
.where(trueCondition())
.apply { attributesFilter(pAttributes) }
)
private fun <T : Record> SelectConditionStep<T>.attributesFilter(pAttributes: List<ProductAttribute>) {
if (pAttributes.isNotEmpty()) {
val filter = pAttributes.joinToString(",") { StringUtils.wrap(it.toString(), "'") }
and("attributes @> ARRAY [$filter]")
}
}
,最后一部分是函数attributesFilter
,它只是连接值并将其粘贴为原始sql
List<ProductAttribute>
是枚举值列表(例如FOR_SALE, INGREDIENT, PRODUCED
)
我缺少可以做的功能&#39;数组包含&#39;在jooq中的操作
如何使用来自attributes @> ARRAY ['PRODUCED', 'INGREDIENT']
的实际值?
List<ProductAttribute>
修改1
尝试了Lukas提出的功能,但它对我不起作用
这就是我现在attributesFilter
中的内容
val field = this.field("products.attributes", TEXT.arrayDataType)
and(field.contains(productAttributes.map { it.toString() }.toTypedArray()))
这个实现给了我这个sql,这是不对的:
"alias_74630789"."products.attributes" @> cast('{"INGREDIENT","FOR_SALE"}' as varchar[])
答案 0 :(得分:1)
我有个好消息。请参阅Field.contains(T)
的Javadoc:
如果您正在使用SQLDialect.POSTGRES,那么您也可以使用此方法来表达&#34; ARRAY包含&#34;运营商。例如:
main.js
// Use this expression
val(new Integer[] { 1, 2, 3 }).contains(new Integer[] { 1, 2 })
// ... to render this SQL
ARRAY[1, 2, 3] @> ARRAY[1, 2]
演员:注意,您似乎遇到了https://github.com/jOOQ/jOOQ/issues/4754。解决方法是使用纯SQL: https://www.jooq.org/doc/latest/manual/sql-building/plain-sql