Skip to content

Commit

Permalink
Merge pull request #142 from hemedani/main
Browse files Browse the repository at this point in the history
fixed delete one due to update relations also
  • Loading branch information
hemedani authored Jan 26, 2024
2 parents 87167fc + d7f9d7a commit 6a0bd2e
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 79 deletions.
4 changes: 4 additions & 0 deletions pages/src/what_is_the_relationship.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ what are a real relationship between `People`?
- Changes on one side of the relationship also affect the other side.
- The two sides of a relationship live together.
- If the relationship leads to the birth of a child, both parties will accept the relationship.
- If one party dies, especially if it's a lover, the other party probably won't want to live either.

Now let's look at the relationship features in `SQL`:
- There is no real relationship. The two sides have only one connection.
- Relationships are not together. And each lives independently.
- Relationships are not deep.
- Relationships do not give birth to any children. (In **Lesan**, you will see that relationships encourage you to create new models)
- If we want to delete one side of the relationship, especially if the other side is dependent on this side, we will only receive an error message.
- And the most important thing is that it is not clear what kind of effects each relationship we create will have on the other side of the relationship.

What are the relationships in `NoSQL`?
Expand All @@ -22,12 +24,14 @@ What are the relationships in `NoSQL`?
- the changes of each party have no effect on the other side and cause many inconsistencies in the data.
- the two sides leave each other after the relationship. Infact, it is not clear what kind of effects each relationship we create will have on the other side of the relationship.
- In this type of databases, they prevent the child from being born, and if a child is born, only one side will be informed of it and probably will not take much responsibility for it.
- There is no management in deleting information and they are easily deleted by either side of the relationship.

And finally what are the relationships in `Lesan`:
- Relationships are as strong as possible, and are described in detail when creating a model.
- Relationships fully contain each other's pure properties within themselves.
- If a relationship changes, all related parties will be notified and apply the changes according to a process.
- By establishing a relationship and seeing many changes on one side of this relationship, you are encouraged to create new relationships. Don't worry, this issue will not add more complexity to the data model, but it will also make the data more understandable. (Below there is an example to understand this)
- Having complete information about relationships, we can prevent the deletion of a document that other documents are dependent on with an error message, and we can recursively delete all dependent documents by setting a small option.
- And the most important point is that it is exactly clear what effects each relationship we have created will have on the other side of the relationship.

## Example
Expand Down
124 changes: 109 additions & 15 deletions src/odm/delete/deleteOne.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IMainRelation } from "../../mod.ts";
import { TSchemas } from "../../models/mod.ts";
import { createProjection } from "../../models/createProjection.ts";
import { getSchema, TSchemas } from "../../models/mod.ts";
import {
Db,
DeleteOptions,
Expand All @@ -8,13 +9,15 @@ import {
ObjectId,
} from "../../npmDeps.ts";
import { throwError } from "../../utils/mod.ts";
import { proccessUpdateOrDeleteRelations } from "../update/findOneAndUpdate.ts";
import { filterDocByProjection } from "../utils/filterDocByProjection.ts";

interface IFindMainRelation extends IMainRelation {
fieldName: string;
collection: string;
}

const processFindMainRelatins = (
const processFindOtherSchemaMainRelatins = (
{ schemasObj, collection }: { schemasObj: TSchemas; collection: string },
) => {
const findMainRelations: IFindMainRelation[] = [];
Expand All @@ -41,7 +44,7 @@ const proccessDeletion = async (
},
) => {
for await (
const mr of processFindMainRelatins({ schemasObj, collection })
const mr of processFindOtherSchemaMainRelatins({ schemasObj, collection })
) {
const findedMr = await db.collection(mr.collection).find({
[`${mr.fieldName}._id`]: _id,
Expand Down Expand Up @@ -83,8 +86,86 @@ export const deleteOne = async <PureFields extends Document = Document>({
const foundedDoc = await db.collection(collection).findOne(
filter as Filter<Document>,
);
const deleteProcces = async () => {
const processFindMainRelatins = (

const deleteOwnRelation = async () => {
const foundedSchema = getSchema(schemasObj, collection);

if (!foundedSchema) {
throwError(`can not find this schema: ${collection}`);
}

const pureDocProjection = createProjection(
schemasObj,
collection,
"Pure",
);

const pureUpdatedDoc = filterDocByProjection(
foundedDoc!,
pureDocProjection,
);

for (const rel in foundedSchema.relations) {
const actualRel = foundedSchema.relations[rel];
const relatedRelations = actualRel.relatedRelations;

if (actualRel.type === "single") {
if (foundedDoc && foundedDoc[rel]) {
const foundedActualRelSingleDoc = await db.collection(
actualRel.schemaName,
).findOne({ _id: foundedDoc[rel]._id });

if (foundedActualRelSingleDoc) {
await proccessUpdateOrDeleteRelations({
db,
collection,
rel,
relatedRelations,
foundedDoc: foundedActualRelSingleDoc,
pureUpdatedDoc,
pureDocProjection,
relationSchemaName: actualRel.schemaName,
isDelete: true,
});
}
}
} else {
if (
foundedDoc && foundedDoc[rel] &&
Array.isArray(foundedDoc[rel])
) {
const relMultiDocs = foundedDoc![rel];

const foundedActualRelMultiDocs = await db.collection(
actualRel.schemaName,
).find({ _id: { $in: relMultiDocs.map((re: any) => re._id) } })
.toArray();

if (foundedActualRelMultiDocs) {
// TODO :: Shoud be updated by one Pipeline
for await (
const eachActualRel of foundedActualRelMultiDocs
) {
await proccessUpdateOrDeleteRelations({
db,
collection,
rel,
relatedRelations,
foundedDoc: eachActualRel,
pureUpdatedDoc,
pureDocProjection,
relationSchemaName: actualRel.schemaName,
isDelete: true,
});
}
}
}
}
}
};

const deleteRelatedRelation = async () => {
const processFindOtherSchemaMainRelatins = (
{ schemasObj, collection }: { schemasObj: TSchemas; collection: string },
) => {
const findMainRelations: IFindMainRelation[] = [];
Expand All @@ -102,19 +183,25 @@ export const deleteOne = async <PureFields extends Document = Document>({
return findMainRelations;
};

const findDocsBasedOnMainRelation = [];
const findDocsBasedOnOtherSchemaMainRelationt = [];

const foundedOtherSchemaMainRelations = processFindOtherSchemaMainRelatins({
schemasObj,
collection,
});

for await (
const mr of processFindMainRelatins({ schemasObj, collection })
const mr of foundedOtherSchemaMainRelations
) {
const findedMr = await db.collection(mr.collection).findOne({
[`${mr.schemaName}._id`]: foundedDoc!._id,
[`${mr.fieldName}._id`]: foundedDoc!._id,
});
findedMr && findDocsBasedOnMainRelation.push({ ...mr, doc: findedMr });
findedMr &&
findDocsBasedOnOtherSchemaMainRelationt.push({ ...mr, doc: findedMr });
}

const deletedData = async () => {
if (findDocsBasedOnMainRelation.length > 0) {
if (findDocsBasedOnOtherSchemaMainRelationt.length > 0) {
await proccessDeletion({
db,
schemasObj,
Expand All @@ -131,18 +218,25 @@ export const deleteOne = async <PureFields extends Document = Document>({

return hardCascade
? await deletedData()
: findDocsBasedOnMainRelation.length === 0
: findDocsBasedOnOtherSchemaMainRelationt.length === 0
? await deletedData()
: throwError(
`please clear below relations status before deletion: ${
JSON.stringify(findDocsBasedOnMainRelation, null, 1).replace(
/\r\n|\n|\r/gm,
"",
)
JSON.stringify(findDocsBasedOnOtherSchemaMainRelationt, null, 1)
.replace(
/\r\n|\n|\r/gm,
"",
)
}`,
);
};

const deleteProcces = async () => {
const deleteRelated = await deleteRelatedRelation();
await deleteOwnRelation();
return deleteRelated;
};

return foundedDoc
? await deleteProcces()
: throwError("can not find this documents");
Expand Down
Loading

0 comments on commit 6a0bd2e

Please sign in to comment.