From 828437f998f17380a5d8bdd0ba08500691778e25 Mon Sep 17 00:00:00 2001 From: Syd Amir Date: Sat, 14 Oct 2023 20:56:27 +0330 Subject: [PATCH] :sparkles: :bug: add insertMany and some little bug fixed --- src/odm/insert/insertMany.ts | 498 +++++++++++++++++++++++++++++++ src/odm/newModel/mod.ts | 19 ++ tests/playground/Configdata.json | 2 +- tests/playground/e2e.ts | 67 ++++- 4 files changed, 584 insertions(+), 2 deletions(-) create mode 100644 src/odm/insert/insertMany.ts diff --git a/src/odm/insert/insertMany.ts b/src/odm/insert/insertMany.ts new file mode 100644 index 00000000..bc59f501 --- /dev/null +++ b/src/odm/insert/insertMany.ts @@ -0,0 +1,498 @@ +import { + BulkWriteOptions, + Db, + Document, + ObjectId, + OptionalUnlessRequiredId, + UpdateFilter, +} from "../../npmDeps.ts"; +import { IRelationsFileds } from "../../mod.ts"; +import { createProjection } from "../../models/createProjection.ts"; +import { schemaFns, TSchemas } from "../../models/mod.ts"; +import { throwError } from "../../utils/mod.ts"; +import { Projection } from "../aggregation/type.ts"; +import { findOne } from "../find/findOne.ts"; +import { find } from "../find/find.ts"; +import { filterDocsByProjection } from "../utils/filterDocsByProjection.ts"; + +export type TInsertRelations = { + [mainKey in keyof T]?: { + _ids: ObjectId | ObjectId[]; + relatedRelations?: { + [key in keyof T[mainKey]["relatedRelations"]]: boolean; + }; + }; +}; + +export const insertMany = async < + TR extends IRelationsFileds, + PureFields extends Document, +>({ + db, + schemasObj, + collection, + docs, + relations, + options, + projection, +}: { + db: Db; + schemasObj: TSchemas; + collection: string; + docs: OptionalUnlessRequiredId[]; + relations?: TInsertRelations; + options?: BulkWriteOptions; + projection?: Projection; +}) => { + const foundedSchema = schemaFns(schemasObj).getSchema(collection); + + const populatedMainRelations = []; + + let generatedDocs = docs.map((doc) => ({ _id: new ObjectId(), ...doc })); + const cloneDocsWithId = [...generatedDocs]; + + const pureDocProjection = createProjection( + schemasObj, + collection, + "Pure", + ); + + // allan bayad ham ba senatio QQ pish beram ham senario somthing is wrong:: aval ye generatedDoc besazam baad hame relationharo peyda konam berizam to ye done arraye ba noe relationha baad age hamechi dorost bood QQ ro start bezanam baad relationharo brooz konam baad insert document to bezanam va baad QQ isFinished ro true konam + + let somethingIsWrong = false; + for (const rel in foundedSchema.relations) { + const pureRelProjection = createProjection( + schemasObj, + foundedSchema.relations[rel].schemaName, + "Pure", + ); + + if (foundedSchema.relations[rel].optional) { + if (relations && relations[rel]) { + if (foundedSchema.relations[rel].type === "single") { + const foundedSingleMainRelation = await findOne({ + db, + collection: foundedSchema.relations[rel].schemaName, + filters: { _id: relations![rel]!._ids }, + }); + + if (!foundedSingleMainRelation) { + throwError(`can not find this relatation : ${rel}`); + } + + const pureOfFoundedSingleMainRelation: Record = {}; + + for (const pureKey in pureRelProjection) { + pureOfFoundedSingleMainRelation[pureKey] = + foundedSingleMainRelation![pureKey]; + } + + generatedDocs = generatedDocs.map((doc) => ({ + ...doc, + [rel]: pureOfFoundedSingleMainRelation, + })); + + for ( + const relatedRel in foundedSchema.relations[rel] + .relatedRelations + ) { + const relatedRelation = + foundedSchema.relations[rel].relatedRelations[relatedRel]; + const relationSchemName = foundedSchema.relations[rel].schemaName; + const updateId: ObjectId = foundedSingleMainRelation!._id; + + if ( + relations && relations[rel] && relations[rel]!.relatedRelations && + relations[rel]!.relatedRelations![relatedRel] === true + ) { + if (relatedRelation.limit) { + if (!relatedRelation.sort) { + throwError("you most be set sort field"); + } + if (relatedRelation.type !== "multiple") { + throwError("you most be set relation type to multiple"); + } + } + + const updateFilter: UpdateFilter = [{ + $addFields: { + [relatedRel]: { + $cond: { + if: { "$ne": [{ "$type": `$${relatedRel}` }, "array"] }, + then: [], + else: `$${relatedRel}`, + }, + }, + }, + }, { + $set: { + [relatedRel]: { + $setUnion: [ + cloneDocsWithId, + `$${relatedRel}`, + ], + }, + }, + }]; + + if (relatedRelation.sort) { + updateFilter.push({ + $set: { + [relatedRel]: { + $sortArray: { + input: `$${relatedRel}`, + sortBy: { + [relatedRelation.sort!.field]: + relatedRelation.sort?.order === "asc" ? 1 : -1, + }, + }, + }, + }, + }); + } + if (relatedRelation.limit) { + updateFilter.push({ + $set: { + [relatedRel]: { + $slice: [`$${relatedRel}`, relatedRelation.limit], + }, + }, + }); + } + + const updatedRel = await db.collection(relationSchemName) + .updateOne( + { + _id: updateId, + }, + updateFilter, + ); + } + } + } else { + const findWithIds = { + _id: { "$in": (relations[rel]!._ids as ObjectId[]) }, + }; + + const foundedMultiMainRelation = await find({ + db, + collection: foundedSchema.relations[rel].schemaName, + filters: findWithIds, + }).toArray(); + + if (!foundedMultiMainRelation) { + throwError(`can not find this relatation : ${rel}`); + } + + if ( + foundedMultiMainRelation.length !== + (relations![rel]!._ids as ObjectId[]).length + ) { + throwError(`we have problem with this relatation : ${rel}`); + } + + const pureOfFoundedMultiMainRelation = filterDocsByProjection( + foundedMultiMainRelation, + pureRelProjection, + ); + + generatedDocs = generatedDocs.map((doc) => ({ + ...doc, + [rel]: pureOfFoundedMultiMainRelation, + })); + + for ( + const relatedRel in foundedSchema.relations[rel] + .relatedRelations + ) { + const relatedRelation = + foundedSchema.relations[rel].relatedRelations[relatedRel]; + const relationSchemName = foundedSchema.relations[rel].schemaName; + + if ( + relations && relations[rel] && relations[rel]!.relatedRelations && + relations[rel]!.relatedRelations![relatedRel] === true + ) { + if (relatedRelation.limit) { + if (!relatedRelation.sort) { + throwError("you most be set sort field"); + } + if (relatedRelation.type !== "multiple") { + throwError("you most be set relation type to multiple"); + } + } + + const updateFilter: UpdateFilter = [{ + $addFields: { + [relatedRel]: { + $cond: { + if: { "$ne": [{ "$type": `$${relatedRel}` }, "array"] }, + then: [], + else: `$${relatedRel}`, + }, + }, + }, + }, { + $set: { + [relatedRel]: { + $setUnion: [ + cloneDocsWithId, + `$${relatedRel}`, + ], + }, + }, + }]; + + if (relatedRelation.sort) { + updateFilter.push({ + $set: { + [relatedRel]: { + $sortArray: { + input: `$${relatedRel}`, + sortBy: { + [relatedRelation.sort!.field]: + relatedRelation.sort?.order === "asc" ? 1 : -1, + }, + }, + }, + }, + }); + } + if (relatedRelation.limit) { + updateFilter.push({ + $set: { + [relatedRel]: { + $slice: [`$${relatedRel}`, relatedRelation.limit], + }, + }, + }); + } + + const updatedRel = await db.collection(relationSchemName) + .updateMany( + findWithIds, + updateFilter, + ); + } + } + } + } + } else { + if (relations && relations[rel]) { + if (foundedSchema.relations[rel].type === "single") { + const foundedSingleMainRelation = await findOne({ + db, + collection: foundedSchema.relations[rel].schemaName, + filters: { _id: relations![rel]!._ids }, + }); + + if (!foundedSingleMainRelation) { + throwError(`can not find this relatation : ${rel}`); + } + + const pureOfFoundedSingleMainRelation: Record = {}; + + for (const pureKey in pureRelProjection) { + pureOfFoundedSingleMainRelation[pureKey] = + foundedSingleMainRelation![pureKey]; + } + + generatedDocs = generatedDocs.map((doc) => ({ + ...doc, + [rel]: pureOfFoundedSingleMainRelation, + })); + + for ( + const relatedRel in foundedSchema.relations[rel] + .relatedRelations + ) { + const relatedRelation = + foundedSchema.relations[rel].relatedRelations[relatedRel]; + const relationSchemName = foundedSchema.relations[rel].schemaName; + const updateId: ObjectId = foundedSingleMainRelation!._id; + + if ( + relations && relations[rel] && relations[rel]!.relatedRelations && + relations[rel]!.relatedRelations![relatedRel] === true + ) { + if (relatedRelation.limit) { + if (!relatedRelation.sort) { + throwError("you most be set sort field"); + } + if (relatedRelation.type !== "multiple") { + throwError("you most be set relation type to multiple"); + } + } + + const updateFilter: UpdateFilter = [{ + $addFields: { + [relatedRel]: { + $cond: { + if: { "$ne": [{ "$type": `$${relatedRel}` }, "array"] }, + then: [], + else: `$${relatedRel}`, + }, + }, + }, + }, { + $set: { + [relatedRel]: { + $setUnion: [ + cloneDocsWithId, + `$${relatedRel}`, + ], + }, + }, + }]; + + if (relatedRelation.sort) { + updateFilter.push({ + $set: { + [relatedRel]: { + $sortArray: { + input: `$${relatedRel}`, + sortBy: { + [relatedRelation.sort!.field]: + relatedRelation.sort?.order === "asc" ? 1 : -1, + }, + }, + }, + }, + }); + } + if (relatedRelation.limit) { + updateFilter.push({ + $set: { + [relatedRel]: { + $slice: [`$${relatedRel}`, relatedRelation.limit], + }, + }, + }); + } + + const updatedRel = await db.collection(relationSchemName) + .updateOne( + { + _id: updateId, + }, + updateFilter, + ); + } + } + } else { + const findWithIds = { + _id: { "$in": (relations[rel]!._ids as ObjectId[]) }, + }; + + const foundedMultiMainRelation = await find({ + db, + collection: foundedSchema.relations[rel].schemaName, + filters: findWithIds, + }).toArray(); + + if (!foundedMultiMainRelation) { + throwError(`can not find this relatation : ${rel}`); + } + + if ( + foundedMultiMainRelation.length !== + (relations![rel]!._ids as ObjectId[]).length + ) { + throwError(`we have problem with this relatation : ${rel}`); + } + + const pureOfFoundedMultiMainRelation = filterDocsByProjection( + foundedMultiMainRelation, + pureRelProjection, + ); + + generatedDocs = generatedDocs.map((doc) => ({ + ...doc, + [rel]: pureOfFoundedMultiMainRelation, + })); + + for ( + const relatedRel in foundedSchema.relations[rel] + .relatedRelations + ) { + const relatedRelation = + foundedSchema.relations[rel].relatedRelations[relatedRel]; + const relationSchemName = foundedSchema.relations[rel].schemaName; + + if ( + relations && relations[rel] && relations[rel]!.relatedRelations && + relations[rel]!.relatedRelations![relatedRel] === true + ) { + if (relatedRelation.limit) { + if (!relatedRelation.sort) { + throwError("you most be set sort field"); + } + if (relatedRelation.type !== "multiple") { + throwError("you most be set relation type to multiple"); + } + } + + const updateFilter: UpdateFilter = [{ + $addFields: { + [relatedRel]: { + $cond: { + if: { "$ne": [{ "$type": `$${relatedRel}` }, "array"] }, + then: [], + else: `$${relatedRel}`, + }, + }, + }, + }, { + $set: { + [relatedRel]: { + $setUnion: [ + cloneDocsWithId, + `$${relatedRel}`, + ], + }, + }, + }]; + + if (relatedRelation.sort) { + updateFilter.push({ + $set: { + [relatedRel]: { + $sortArray: { + input: `$${relatedRel}`, + sortBy: { + [relatedRelation.sort!.field]: + relatedRelation.sort?.order === "asc" ? 1 : -1, + }, + }, + }, + }, + }); + } + if (relatedRelation.limit) { + updateFilter.push({ + $set: { + [relatedRel]: { + $slice: [`$${relatedRel}`, relatedRelation.limit], + }, + }, + }); + } + + const updatedRel = await db.collection(relationSchemName) + .updateMany( + findWithIds, + updateFilter, + ); + } + } + } + } else { + throwError(`can not find this relatation : ${rel}`); + } + } + } + + await db.collection(collection).insertMany(generatedDocs, options); + + return generatedDocs; +}; diff --git a/src/odm/newModel/mod.ts b/src/odm/newModel/mod.ts index 6cc5a037..37aaa32d 100644 --- a/src/odm/newModel/mod.ts +++ b/src/odm/newModel/mod.ts @@ -28,6 +28,7 @@ import { insertOne, TInsertRelations } from "../insert/insertOne.ts"; import { addRelation } from "../relation/addRelation.ts"; import { updateById } from "../update/updateById.ts"; import { updateOne } from "../update/updateOne.ts"; +import { insertMany } from "../insert/insertMany.ts"; export const newModel = < PF extends IPureFields, @@ -113,6 +114,24 @@ export const newModel = < projection, }), + insertMany: ( + { docs, relations, options, projection }: { + docs: OptionalUnlessRequiredId[]; + relations?: TInsertRelations; + options?: InsertOptions; + projection?: Projection; + }, + ) => + insertMany({ + db, + schemasObj, + collection: name, + docs, + relations, + options, + projection, + }), + addRelation: ({ _id, relations, projection, replace }: { relations: TInsertRelations; projection?: Projection; diff --git a/tests/playground/Configdata.json b/tests/playground/Configdata.json index 6bc9ef60..9e754a00 100644 --- a/tests/playground/Configdata.json +++ b/tests/playground/Configdata.json @@ -1 +1 @@ -[{"id":"lnado0z3xqidkxzr3c","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"country\",\n \"act\": \"addCountry\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Iran\",\n \"population\": 999,\n \"abb\": \"IR\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"countryId","value":"[body][_id]"}]},{"id":"lnadmulojyoassts5hm","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Hamedan\",\n \"population\": 10,\n \"abb\": \"HM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"hamedanId","value":"[body][_id]"}]},{"id":"lnae0ntog92w5l8gpm","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Tehran\",\n \"population\": 50,\n \"abb\": \"TH\",\n \"country\": \"{countryId}\",\n \"isCapital\": true\n }\n }\n }\n}","repeat":1,"captures":[{"key":"tehranId","value":"[body][_id]"}]},{"id":"lnaeipsiuzcq26p7dj","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Kerman\",\n \"population\": 12,\n \"abb\": \"KM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"kermanId","value":"[body][_id]"}]},{"id":"lnaep6ixtztjq4348f","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Esfahan\",\n \"population\": 25,\n \"abb\": \"ES\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"esfahanId","value":"[body][_id]"}]},{"id":"lnaerzg6fuea94nojep","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Mashhad\",\n \"population\": 28,\n \"abb\": \"MS\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnaetuhirjl9nkhylv","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Tabriz\",\n \"population\": 27,\n \"abb\": \"TB\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafe8cemgy81p8d16","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Qum\",\n \"population\": 18,\n \"abb\": \"QM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafhyfkh1x6d3y0vjs","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Yazd\",\n \"population\": 16,\n \"abb\": \"YZ\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"yazdId","value":"[body][_id]"}]},{"id":"lnafjk1la3tr22hyain","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Bushehr\",\n \"population\": 17,\n \"abb\": \"BU\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafkbpdeijcs1z4ew","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Khozestan\",\n \"population\": 21,\n \"abb\": \"KH\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafl7y03ypve5ppqzx","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Malayer\",\n \"population\": 5,\n \"abb\": \"ML\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnaflz55eanabzaheaq","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Toyserkan\",\n \"population\": 6,\n \"abb\": \"TO\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnahwje7asyuuo5zzhh","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"country\",\n \"act\": \"getCountries\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"provincesAsc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"provincesDesc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"provincesByPopAsc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"proviceByPopDesc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"capitalProvince\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"page\": 1,\n \"limit\": 10\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnbn2fifqmtflpiljhb","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"user\",\n \"act\": \"addUser\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1,\n \"livedProvinces\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n }\n },\n \"set\": {\n \"name\": \"Syd Amir\",\n \"age\": 36,\n \"country\": \"{countryId}\",\n \"livedProvinces\": [\n \"{hamedanId}\",\n \"{tehranId}\"\n ]\n }\n }\n }\n}","repeat":1,"captures":[{"key":"userId","value":"[body][_id]"}]},{"id":"lnedpvhpf4ijrhyb6ir","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"user\",\n \"act\": \"addUserLivedProvinces\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1,\n \"livedProvinces\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n }\n },\n \"set\": {\n \"_id\": \"{userId}\",\n \"livedProvinces\": [\n \"{esfahanId}\",\n \"{kermanId}\",\n \"{yazdId}\",\n \"{hamedanId}\",\n \"{tehranId}\"\n ]\n }\n }\n }\n}","repeat":1,"captures":[]}] \ No newline at end of file +[{"id":"lnado0z3xqidkxzr3c","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"country\",\n \"act\": \"addCountry\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Iran\",\n \"population\": 999,\n \"abb\": \"IR\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"countryId","value":"[body][_id]"}]},{"id":"lnadmulojyoassts5hm","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Hamedan\",\n \"population\": 10,\n \"abb\": \"HM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"hamedanId","value":"[body][_id]"}]},{"id":"lnae0ntog92w5l8gpm","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Tehran\",\n \"population\": 50,\n \"abb\": \"TH\",\n \"country\": \"{countryId}\",\n \"isCapital\": true\n }\n }\n }\n}","repeat":1,"captures":[{"key":"tehranId","value":"[body][_id]"}]},{"id":"lnaeipsiuzcq26p7dj","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Kerman\",\n \"population\": 12,\n \"abb\": \"KM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"kermanId","value":"[body][_id]"}]},{"id":"lnaep6ixtztjq4348f","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Esfahan\",\n \"population\": 25,\n \"abb\": \"ES\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"esfahanId","value":"[body][_id]"}]},{"id":"lnaerzg6fuea94nojep","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Mashhad\",\n \"population\": 28,\n \"abb\": \"MS\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnaetuhirjl9nkhylv","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Tabriz\",\n \"population\": 27,\n \"abb\": \"TB\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafe8cemgy81p8d16","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Qum\",\n \"population\": 18,\n \"abb\": \"QM\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafhyfkh1x6d3y0vjs","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Yazd\",\n \"population\": 16,\n \"abb\": \"YZ\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[{"key":"yazdId","value":"[body][_id]"}]},{"id":"lnafjk1la3tr22hyain","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Bushehr\",\n \"population\": 17,\n \"abb\": \"BU\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafkbpdeijcs1z4ew","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Khozestan\",\n \"population\": 21,\n \"abb\": \"KH\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnafl7y03ypve5ppqzx","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Malayer\",\n \"population\": 5,\n \"abb\": \"ML\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnaflz55eanabzaheaq","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvince\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"name\": \"Toyserkan\",\n \"population\": 6,\n \"abb\": \"TO\",\n \"country\": \"{countryId}\"\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnahwje7asyuuo5zzhh","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"country\",\n \"act\": \"getCountries\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"provincesAsc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"provincesDesc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"provincesByPopAsc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"proviceByPopDesc\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"capitalProvince\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"page\": 1,\n \"limit\": 10\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnbn2fifqmtflpiljhb","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"user\",\n \"act\": \"addUser\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1,\n \"livedProvinces\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n }\n },\n \"set\": {\n \"name\": \"Syd Amir\",\n \"age\": 36,\n \"country\": \"{countryId}\",\n \"livedProvinces\": [\n \"{hamedanId}\",\n \"{tehranId}\"\n ]\n }\n }\n }\n}","repeat":1,"captures":[{"key":"userId","value":"[body][_id]"}]},{"id":"lnedpvhpf4ijrhyb6ir","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"user\",\n \"act\": \"addUserLivedProvinces\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1,\n \"livedProvinces\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n }\n },\n \"set\": {\n \"_id\": \"{userId}\",\n \"livedProvinces\": [\n \"{esfahanId}\",\n \"{kermanId}\",\n \"{yazdId}\",\n \"{hamedanId}\",\n \"{tehranId}\"\n ]\n }\n }\n }\n}","repeat":1,"captures":[]},{"id":"lnq7wmyl3mfcgw56c9e","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"country\",\n \"act\": \"addCountries\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"set\": {\n \"multiCountries\": [\n {\n \"name\": \"Afghanistan\",\n \"population\": 453,\n \"abb\": \"AF\"\n },\n {\n \"name\": \"Iraq\",\n \"population\": 685,\n \"abb\": \"IQ\"\n }\n ]\n }\n }\n }\n}","repeat":1,"captures":[{"key":"AfghanistanId","value":"[body][0][_id]"},{"key":"IraqId","value":"[body][1][_id]"}]},{"id":"lnqas441f2xjtesnpe","bodyHeaders":"{\n \"headers\": {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"\"\n },\n \"body\": {\n \"service\": \"main\",\n \"model\": \"province\",\n \"act\": \"addProvinces\",\n \"details\": {\n \"get\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1,\n \"country\": {\n \"_id\": 1,\n \"name\": 1,\n \"population\": 1,\n \"abb\": 1\n },\n \"users\": {\n \"_id\": 1,\n \"name\": 1,\n \"age\": 1\n }\n },\n \"set\": {\n \"multiProvinces\": [\n {\n \"name\": \"Basreh\",\n \"population\": 5,\n \"abb\": \"BS\"\n },\n {\n \"name\": \"Karbala\",\n \"population\": 8,\n \"abb\": \"KR\"\n },\n {\n \"name\": \"Baghdad\",\n \"population\": 15,\n \"abb\": \"BG\"\n },\n {\n \"name\": \"Samera\",\n \"population\": 3,\n \"abb\": \"SM\"\n },\n {\n \"name\": \"Kazemein\",\n \"population\": 10,\n \"abb\": \"KZ\"\n }\n ],\n \"country\": \"{IraqId}\"\n }\n }\n }\n}","repeat":1,"captures":[]}] \ No newline at end of file diff --git a/tests/playground/e2e.ts b/tests/playground/e2e.ts index 12a0f98a..fb57eaaa 100644 --- a/tests/playground/e2e.ts +++ b/tests/playground/e2e.ts @@ -162,6 +162,29 @@ coreApp.acts.setAct({ fn: addCountry, }); +// ------------------ Add Multiple Countries ------------------ +const addMultipleCountriesValidator = () => { + return object({ + set: (object({ multiCountries: array(object()) })), + get: coreApp.schemas.selectStruct("country", { users: 1 }), + }); +}; + +const addCountries: ActFn = async (body) => { + const { multiCountries } = body.details.set; + return await countries.insertMany({ + docs: multiCountries, + projection: body.details.get, + }); +}; + +coreApp.acts.setAct({ + schema: "country", + actName: "addCountries", + validator: addMultipleCountriesValidator(), + fn: addCountries, +}); + // ------------------ Get Countries ------------------ const getCountriesValidator = () => { return object({ @@ -233,8 +256,10 @@ const addProvinceValidator = () => { get: coreApp.schemas.selectStruct("province", 1), }); }; + const addProvince: ActFn = async (body) => { const { country, isCapital, name, population, abb } = body.details.set; + return await provinces.insertOne({ doc: { name, population, abb }, projection: body.details.get, @@ -252,6 +277,7 @@ const addProvince: ActFn = async (body) => { }, }); }; + coreApp.acts.setAct({ schema: "province", actName: "addProvince", @@ -259,6 +285,45 @@ coreApp.acts.setAct({ fn: addProvince, }); +// ------------------ Add Multiple Provinces ------------------ +const addProvincesValidator = () => { + return object({ + set: object({ + multiProvinces: array(object()), + country: string(), + }), + get: coreApp.schemas.selectStruct("province", 1), + }); +}; + +const addProvinces: ActFn = async (body) => { + const { country, multiProvinces } = body.details.set; + + return await provinces.insertMany({ + docs: multiProvinces, + projection: body.details.get, + relations: { + country: { + _ids: new ObjectId(country), + relatedRelations: { + provincesAsc: true, + provincesDesc: true, + provincesByPopAsc: true, + proviceByPopDesc: true, + capitalProvince: false, + }, + }, + }, + }); +}; + +coreApp.acts.setAct({ + schema: "province", + actName: "addProvinces", + validator: addProvincesValidator(), + fn: addProvinces, +}); + // ------------------ Get Province ------------------ const getProvincesValidator = () => { return object({ @@ -277,8 +342,8 @@ const getProvinces: ActFn = async (body) => { } = body.details; const pipeline = []; - pipeline.push({ $limit: take }); pipeline.push({ $skip: (page - 1) * take }); + pipeline.push({ $limit: take }); countryId && pipeline.push({ $match: { "country._id": new ObjectId(countryId) } });