如何通过深度嵌套的 jsonb 数据创建带有顺序的查询?
How to create a query with order by deeply nested jsonb data?
我有一个包含 4 列的 table availability
:productcode
、currency
、bookableitems
、summary
.
bookableitems
是 JSONB。
我需要 select 所有包含 currency = 'USD'
和 productOptionCode = 'TG11'
以及 ORDER BY [recommendedRetailPrice of ageBand = 'CHILD'] DESC
的记录。
currency
和 productOptionCode
的选择很简单:
SELECT *
FROM availability
WHERE currency = 'USD' AND bookableitems @> '[{"productOptionCode": "TG11"}]'
但我找不到如何按如此深的数据排序的示例(尤其是如何执行 4 个嵌套循环,bookableitems
、seasons
、pricingRecords
和 pricingDetails
为了找到 ageBand = 'CHILD'
).
一行示例:
"productcode": "46258P1",
"currency": "USD",
"bookableitems": [
{
"seasons": [
{
"startDate": "2019-08-12",
"pricingRecords": [
{
"daysOfWeek": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
"timedEntries": [{"startTime": "20:30"}],
"pricingDetails": [
{
"price": {
"original": {
"bookingFee": 8.69,
"partnerNetPrice": 115.87,
"partnerTotalPrice": 124.56,
"recommendedRetailPrice": 139.49
}
},
"ageBand": "CHILD",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
},
{
"price": {
"original": {
"bookingFee": 11.57,
"partnerNetPrice": 154.21,
"partnerTotalPrice": 165.78,
"recommendedRetailPrice": 185.65
}
},
"ageBand": "ADULT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
]
}
]
}
],
"productOptionCode": "TG11"
},
{
"seasons": [
{
"startDate": "2019-08-12",
"pricingRecords": [
{
"daysOfWeek": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
"timedEntries": [{"startTime": "20:30"}],
"pricingDetails": [
{
"price": {
"original": {
"bookingFee": 0.0,
"partnerNetPrice": 0.0,
"partnerTotalPrice": 0.0,
"recommendedRetailPrice": 0.0
}
},
"ageBand": "INFANT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
},
{
"price": {
"original": {
"bookingFee": 8.95,
"partnerNetPrice": 119.28,
"partnerTotalPrice": 128.23,
"recommendedRetailPrice": 143.59
}
},
"ageBand": "ADULT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
]
}
]
}
],
"productOptionCode": "TG1"
}
],
"summary": {"fromPrice": 185.65}
PostgreSQL v13.
有人可以告诉我正确的查询吗?
在对数据进行操作时,没有 PostgreSQL 索引会同时直接满足所有这些要求,除非我们假设 'TG11' 是硬编码的而不是可变参数(这似乎不太可能)。
这里是查询:
SELECT *, jsonb_path_query(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")') -> 'price' -> 'original' -> 'recommendedRetailPrice' AS retailPrice
FROM availability as a
WHERE currency = 'USD' AND bookableitems @> '[{"productOptionCode": "TG11"}]'
ORDER BY retailPrice DESC;
这个请求jsonb_path_query(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")')
returns这个对象:
{
"price": {
"original": {
"bookingFee": 8.69,
"partnerNetPrice": 115.87,
"partnerTotalPrice": 124.56,
"recommendedRetailPrice": 139.49
}
},
"ageBand": "CHILD",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
然后 -> 'price' -> 'original' -> 'recommendedRetailPrice' AS retailPrice
简单地将 recommendedRetailPrice
提取为 retailPrice
以用于 ORDER BY
部分。
如果有人需要检查“CHILD”是否存在,只需添加:
AND jsonb_path_exists(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")')
在 WHERE 部分内。
我有一个包含 4 列的 table availability
:productcode
、currency
、bookableitems
、summary
.
bookableitems
是 JSONB。
我需要 select 所有包含 currency = 'USD'
和 productOptionCode = 'TG11'
以及 ORDER BY [recommendedRetailPrice of ageBand = 'CHILD'] DESC
的记录。
currency
和 productOptionCode
的选择很简单:
SELECT *
FROM availability
WHERE currency = 'USD' AND bookableitems @> '[{"productOptionCode": "TG11"}]'
但我找不到如何按如此深的数据排序的示例(尤其是如何执行 4 个嵌套循环,bookableitems
、seasons
、pricingRecords
和 pricingDetails
为了找到 ageBand = 'CHILD'
).
一行示例:
"productcode": "46258P1",
"currency": "USD",
"bookableitems": [
{
"seasons": [
{
"startDate": "2019-08-12",
"pricingRecords": [
{
"daysOfWeek": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
"timedEntries": [{"startTime": "20:30"}],
"pricingDetails": [
{
"price": {
"original": {
"bookingFee": 8.69,
"partnerNetPrice": 115.87,
"partnerTotalPrice": 124.56,
"recommendedRetailPrice": 139.49
}
},
"ageBand": "CHILD",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
},
{
"price": {
"original": {
"bookingFee": 11.57,
"partnerNetPrice": 154.21,
"partnerTotalPrice": 165.78,
"recommendedRetailPrice": 185.65
}
},
"ageBand": "ADULT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
]
}
]
}
],
"productOptionCode": "TG11"
},
{
"seasons": [
{
"startDate": "2019-08-12",
"pricingRecords": [
{
"daysOfWeek": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"],
"timedEntries": [{"startTime": "20:30"}],
"pricingDetails": [
{
"price": {
"original": {
"bookingFee": 0.0,
"partnerNetPrice": 0.0,
"partnerTotalPrice": 0.0,
"recommendedRetailPrice": 0.0
}
},
"ageBand": "INFANT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
},
{
"price": {
"original": {
"bookingFee": 8.95,
"partnerNetPrice": 119.28,
"partnerTotalPrice": 128.23,
"recommendedRetailPrice": 143.59
}
},
"ageBand": "ADULT",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
]
}
]
}
],
"productOptionCode": "TG1"
}
],
"summary": {"fromPrice": 185.65}
PostgreSQL v13.
有人可以告诉我正确的查询吗?
在对数据进行操作时,没有 PostgreSQL 索引会同时直接满足所有这些要求,除非我们假设 'TG11' 是硬编码的而不是可变参数(这似乎不太可能)。
这里是查询:
SELECT *, jsonb_path_query(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")') -> 'price' -> 'original' -> 'recommendedRetailPrice' AS retailPrice
FROM availability as a
WHERE currency = 'USD' AND bookableitems @> '[{"productOptionCode": "TG11"}]'
ORDER BY retailPrice DESC;
这个请求jsonb_path_query(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")')
returns这个对象:
{
"price": {
"original": {
"bookingFee": 8.69,
"partnerNetPrice": 115.87,
"partnerTotalPrice": 124.56,
"recommendedRetailPrice": 139.49
}
},
"ageBand": "CHILD",
"minTravelers": 1,
"pricingPackageType": "PER_PERSON"
}
然后 -> 'price' -> 'original' -> 'recommendedRetailPrice' AS retailPrice
简单地将 recommendedRetailPrice
提取为 retailPrice
以用于 ORDER BY
部分。
如果有人需要检查“CHILD”是否存在,只需添加:
AND jsonb_path_exists(a.bookableitems, '$[*].seasons[*].pricingRecords[*].pricingDetails[*] ? (@.ageBand == "CHILD")')
在 WHERE 部分内。