mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
adjusted
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
const { Sequelize } = require('sequelize')
|
||||
|
||||
/**
|
||||
* Strips a key from every element in a JSONB array using PostgreSQL's
|
||||
* jsonb_agg + #- operator in a subquery.
|
||||
*
|
||||
* @param {string} column - JSONB column e.g. "personal_info"
|
||||
* @param {string} arrayField - array field name e.g. "addresses"
|
||||
* @param {string[]} keys - keys to strip from each array element e.g. ["street", "zip"]
|
||||
* @returns {string} SQL fragment
|
||||
*/
|
||||
function buildArrayStrip(column, arrayField, keys) {
|
||||
const keyRemovals = keys.reduce(
|
||||
(acc, key) => `(${acc} #- '{${key}}')`,
|
||||
"elem"
|
||||
);
|
||||
|
||||
return `(
|
||||
SELECT jsonb_agg(${keyRemovals})
|
||||
FROM jsonb_array_elements("${column}"->'${arrayField}') AS elem
|
||||
)`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a Sequelize literal that strips JSONB paths at the DB level.
|
||||
* Supports:
|
||||
* - nested keys: "personal_info.name.given_name"
|
||||
* - array item keys: "personal_info.addresses[].street"
|
||||
*
|
||||
* @param {string} column - JSONB column name e.g. "personal_info"
|
||||
* @param {string[]} excludePaths - dot-notation paths
|
||||
* @returns {Array|null} Sequelize literal attribute tuple
|
||||
*/
|
||||
function excludeJsonbPaths(column, excludePaths = []) {
|
||||
const nestedPaths = excludePaths.filter(
|
||||
(p) => p.startsWith(`${column}.`) && !p.includes("[]")
|
||||
);
|
||||
|
||||
const arrayPaths = excludePaths.filter(
|
||||
(p) => p.startsWith(`${column}.`) && p.includes("[]")
|
||||
);
|
||||
|
||||
// ─── Group array paths ──────────────────────────────────────────────────────
|
||||
// Separate bare array strips → "personal_info.addresses[]"
|
||||
// from key-level strips → "personal_info.addresses[].city"
|
||||
const bareArrayStrips = new Set(); // fields to remove entirely e.g. "addresses"
|
||||
const arrayGroups = {}; // fields to partially strip e.g. { addresses: ["city"] }
|
||||
|
||||
for (const path of arrayPaths) {
|
||||
const stripped = path.replace(`${column}.`, ""); // "addresses[].city" or "addresses[]"
|
||||
|
||||
if (stripped.endsWith("[]")) {
|
||||
// ─── Bare array strip — remove the whole field ─────────────────────────
|
||||
const arrayField = stripped.replace("[]", "");
|
||||
bareArrayStrips.add(arrayField);
|
||||
} else {
|
||||
// ─── Key-level strip — remove specific keys inside each element ────────
|
||||
const [arrayPart, key] = stripped.split("[]."); // ["addresses", "city"]
|
||||
const arrayField = arrayPart.replace("[]", "");
|
||||
|
||||
// Skip if the whole array is already being stripped entirely
|
||||
if (bareArrayStrips.has(arrayField)) continue;
|
||||
|
||||
if (!arrayGroups[arrayField]) arrayGroups[arrayField] = [];
|
||||
arrayGroups[arrayField].push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nestedPaths.length && !bareArrayStrips.size && !Object.keys(arrayGroups).length)
|
||||
return null;
|
||||
|
||||
let literal = `"${column}"`;
|
||||
|
||||
// ─── 1. Strip nested keys ───────────────────────────────────────────────────
|
||||
for (const path of nestedPaths) {
|
||||
const keys = path.replace(`${column}.`, "").split(".");
|
||||
literal = `(${literal} #- '{${keys.join(",")}}')`;
|
||||
}
|
||||
|
||||
// ─── 2. Strip entire array fields ──────────────────────────────────────────
|
||||
for (const arrayField of bareArrayStrips) {
|
||||
literal = `(${literal} #- '{${arrayField}}')`;
|
||||
}
|
||||
|
||||
// ─── 3. Strip specific keys inside array elements ──────────────────────────
|
||||
for (const [arrayField, keys] of Object.entries(arrayGroups)) {
|
||||
const arrayStrip = buildArrayStrip(column, arrayField, keys);
|
||||
literal = `jsonb_set(${literal}, '{${arrayField}}', COALESCE(${arrayStrip}, '[]'))`;
|
||||
}
|
||||
|
||||
return [Sequelize.literal(literal), column];
|
||||
}
|
||||
|
||||
module.exports = { excludeJsonbPaths };
|
||||
Reference in New Issue
Block a user