@360-l/mongo-bulk-data-migration
Version:
MongoDB bulk data migration for node scripts
128 lines (127 loc) • 6.15 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeRollbackQuery = computeRollbackQuery;
const lodash_1 = __importDefault(require("lodash"));
const flattenDocument_1 = require("../tools/flattenDocument");
const arrayFiltersUtils = __importStar(require("../tools/arrayFilters"));
function computeRollbackQuery(updateQuery, backup) {
const unsetPropertiesDuringUpdate = Object.keys(updateQuery.$unset || {});
const setPropertiesDuringUpdate = Object.keys(updateQuery.$set || {});
const $set = computeRollbackSet(setPropertiesDuringUpdate, unsetPropertiesDuringUpdate, backup);
const $unsetWithoutPositionals = computeRollbackUnset(setPropertiesDuringUpdate, backup, $set);
const { arrayFilters, unsetAdditionalPositional } = _computeArrayFilterAndUnsetWithPositionals(updateQuery, backup);
const $unset = {
...$unsetWithoutPositionals,
...unsetAdditionalPositional,
};
return {
...(!lodash_1.default.isEmpty($set) ? { $set } : {}),
...(!lodash_1.default.isEmpty($unset) ? { $unset } : {}),
...(!lodash_1.default.isEmpty(arrayFilters) ? { arrayFilters } : {}),
};
}
function _computeArrayFilterAndUnsetWithPositionals(updateQuery, backup) {
const unsetAdditionalPositional = {};
const filteredObject = Object.keys((0, flattenDocument_1.flattenDocument)(backup));
const arrayFilters = [];
const update = Object.keys((0, flattenDocument_1.flattenDocument)(updateQuery.$set ?? {}));
update
.filter((path) => !filteredObject.includes(path) &&
!arrayFiltersUtils.hasPathMatchingPositionalOperators(path, filteredObject))
.forEach((path) => {
if (arrayFiltersUtils.isArrayFilterPath(path)) {
unsetAdditionalPositional[path] = 1;
arrayFilters.push(...arrayFiltersUtils.buildArrayFiltersOptionToUnset(path));
}
});
return {
arrayFilters,
unsetAdditionalPositional,
};
}
function computeRollbackSet(setPropertiesDuringUpdate, unsetPropertiesDuringUpdate, backup) {
const flattenBackupDocument = (0, flattenDocument_1.flattenDocument)(backup);
return Object.entries(flattenBackupDocument).reduce((rollbackSet, [key, value]) => {
const parentKeyToFullyRestore = [
...setPropertiesDuringUpdate,
...unsetPropertiesDuringUpdate
].find((setOrUnsetKey) => key.startsWith(`${setOrUnsetKey}.`));
if (parentKeyToFullyRestore && parentKeyToFullyRestore in backup) {
rollbackSet[parentKeyToFullyRestore] = backup[parentKeyToFullyRestore];
return rollbackSet;
}
const indexMatch = /(.*)\.(\d+)$/.exec(key);
if (indexMatch) {
const [_str, nestedPathToArray, index] = indexMatch;
if (Array.isArray(lodash_1.default.get(backup, nestedPathToArray))) {
const containsDeeperSubKey = setPropertiesDuringUpdate.some((propertySet) => propertySet !== key &&
propertySet.match(new RegExp(`^${nestedPathToArray}\\.\\d+\\.`)));
if (!containsDeeperSubKey) {
if (typeof rollbackSet[nestedPathToArray] === 'undefined') {
rollbackSet[nestedPathToArray] = [];
}
rollbackSet[nestedPathToArray][Number(index)] = value;
}
else {
rollbackSet[`${nestedPathToArray}.${index}`] = value;
}
return rollbackSet;
}
}
rollbackSet[key] = value;
return rollbackSet;
}, {});
}
function computeRollbackUnset(setPropertiesDuringUpdate, backup, $set) {
const keysToSet = Object.keys($set);
const keysToUnset = setPropertiesDuringUpdate.filter((path) => !keysToSet.includes(path) &&
!arrayFiltersUtils.isArrayFilterPath(path) &&
!keysToSet.some((key) => path.startsWith(`${key}.`)));
const parentKeysToUnset = computeParentKeysToUnset(keysToUnset, backup);
const nonConflictingKeysToUnset = filterConflictingKeys([
...keysToUnset,
...parentKeysToUnset,
]);
const entriesToUnset = nonConflictingKeysToUnset.map((key) => [key, 1]);
return Object.fromEntries(entriesToUnset);
}
function computeParentKeysToUnset(nestedKeysToUnset, backup) {
return nestedKeysToUnset.reduce((parentKeysToUnset, key) => {
const splitParentKeys = key.split('.').slice(0, -1);
const parentKeyNestedPaths = splitParentKeys.map((_key, offset) => splitParentKeys.slice(0, offset + 1).join('.'));
const keysToUnset = parentKeyNestedPaths.filter((parentKey) => !lodash_1.default.has(backup, parentKey));
return parentKeysToUnset.concat(keysToUnset);
}, []);
}
function filterConflictingKeys(keys) {
return keys.filter((key) => {
const nestedParentKey = key.split('.').slice(0, -1).join('.');
return !keys.includes(nestedParentKey);
});
}