Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support advanced aggregate pipeline to update outside the aggregate source #12

Open
2 tasks
elisap360 opened this issue Jun 17, 2024 · 1 comment
Open
2 tasks

Comments

@elisap360
Copy link

Context

I needed to update a field on collection companies by filtering elements on group collection.
With the current DataMigration architecture, the target collection must be the one we want to update. But in this case, it proved counter-productive, the join was too big and the script crashed.

Sample script
import { MongoBulkDataMigration } from "@360-l/mongo-bulk-data-migration";
import { DataMigrationProcess } from "@backend/utils/env/load/script/datamigration";
import { $nex } from "@backend/utils/mongo/utils";
import type { Company } from "@backend/utils/mongo/definitions";

const MIGRATION_ID = "migration_20240527T110000Z-activateMagicLinkForNonCustomizedUrlCompanies";

const processHandler = new DataMigrationProcess({ name: MIGRATION_ID }, buildMigration);
void processHandler.handleMigration();

export function buildMigration() {
    return new MongoBulkDataMigration<Company>({
        db: global._mongoClient.db(),
        id: MIGRATION_ID,
        collectionName: "companies",
        projection: { loginWithMagicLink: 1 },
        query: [
            {
                "$lookup": {
                    "from": "groups",
                    "localField": "_id",
                    "foreignField": "company",
                    "as": "groups"
                }
            }, {
                "$project": {
                    "loginWithMagicLink": 1,
                    "rootGroup": {
                        "$filter": {
                            "input": "$groups",
                            "as": "rootGroup",
                            "cond": {
                                "$eq": [
                                    "others", "$$rootGroup.sys"
                                ]
                            }
                        }
                    }
                }
            }, {
                "$unwind": {
                    "path": "$rootGroup"
                }
            }, {
                "$project": {
                    "loginWithMagicLink": 1,
                    "subdomain": "$rootGroup.subdomain",
                    "url": "$rootGroup.url"
                }
            }, {
                "$match": {
                    $or: [
                        { loginWithMagicLink: $nex },
                        { loginWithMagicLink: false }
                    ],
                    $and: [{
                        $or: [
                            { subdomain: $nex },
                            { subdomain: "" }
                        ] }, {
                        $or: [
                            { url: $nex },
                            { url: "" }
                        ] }
                    ]
                }
            }
        ],
        update: {
            $set: {
                loginWithMagicLink: true
            }
        }
    });
}

TO DO

  • support update outside the aggregate source (it could be new parameters to indicate the source/destination collections)
  • make it work with the rollback system
Sample script
    return new MongoBulkDataMigration<Company>({
        db: global._mongoClient.db(),
        id: MIGRATION_ID,
        collection: {
            query: "groups",
            update: "companies",
            relatedIdKey: "company", // groups._id -> companies.company
        },
        projection: { company:1, sys:1, subdomain:1, url:1 },
        query: {
            sys: "others",
            $and: [...]
        },
        update: async (group) => {
            const company = await companyRepository.fetchById(group.company, ["_id", "loginWithMagicLink"]);
            if (! company.loginWithMagicLink) {
                companyIdsToSave.push(company._id);
                await _db.companies.update(company._id, { $set: { loginWithMagicLink: true } });
            }
        })
    });
@elisap360
Copy link
Author

@pp0rtal I finally created a ticket !
I don't have a better idea than what you proposed, it would be very helpful already =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant