deleteOne functions

Deletion has the same problems as update.

Delete a User

Pay attention to the following code:

const deleteUserValidator = () => {
  return object({
    set: object({
      _id: string(),
    }),
    get: object({
      success: optional(enums([0, 1])),
    }),
  });
};

const deleteUser: ActFn = async (body) => {
  const {
    set: { _id },
    get,
  } = body.details;
  return await users.deleteOne({
    filter: { _id: new ObjectId(_id) },
  });
};

coreApp.acts.setAct({
  schema: "user",
  actName: "deleteUser",
  validator: deleteUserValidator(),
  fn: deleteUser,
});

If you remember, when we defined a relationship for the user, we gave it the following object as a relationship:

{
  livedCities: {
    optional: false,
    schemaName: "city",
    type: "multiple",
    sort: {
      field: "_id",
      order: "desc",
    },
    relatedRelations: {
      users: {
        type: "multiple",
        limit: 50,
        sort: {
          field: "_id",
          order: "desc",
        },
      },
    },
  },

  country: {
    optional: false,
    schemaName: "country",
    type: "single",
    relatedRelations: {
      users: {
        type: "multiple",
        limit: 50,
        sort: {
          field: "_id",
          order: "desc",
        },
      },
    },
  },
}

Fortunately, all the relationships that exist for the user are the ones we have defined above, and there is no relatedRelation for the user. user-schema-for-delete

That's why we said fortunately, because if a document has relatedRelations, by deleting that document, some documents may be meaningless or not used. For example, if we want to delete a country in the example we have completed so far, the cities belonging to that country will become meaningless data.

There is no problem for users and we can simply use delete without other data being unused. But by deleting each user, we have to check its mainRelations and if the user is stored as an embed, delete the user there, and if another user needs to be added to the embed list, add the other user as well.

In our example, we have to check the embedded list of users in the cities where the user lives, as well as the list of users in the country belonging to that user.

You can find full example here and test the deleteOne method in local computer.

bfore execut mainuserdeleteUser:
15-0-before-execute-delete-user

executing mainuserdeleteUser:
15-1-delete-user-executing

after execut mainuserdeleteUser:
15-2-after-delete-user

Add E2E Test

For adding deleteUser request to E2E section you should click on the e2e button (like bottom picture) to add your request to E2E section.

e2e sequence

Then, in the E2E section and deleteUser sequence, you should replace the user id that you set capture in own sequence with default user id. default user id in deleteUser sequence is like below picture.

e2e sequence

The replaced country id is like below picture.

e2e sequence

Delete a Country

What if we want to remove a country? Although we have not defined any relationship for the country, both the city and the user have created relationships with the country.

const countryRelations = {};

const cityRelations = {
  country: {
    optional: false,
    schemaName: "country",
    type: "single" as RelationDataType,
    relatedRelations: {
      cities: {
        type: "multiple" as RelationDataType,
        limit: 50,
        sort: {
          field: "_id",
          order: "desc" as RelationSortOrderType,
        },
      },
      citiesByPopulation: {
        type: "multiple" as RelationDataType,
        limit: 50,
        sort: {
          field: "population",
          order: "desc" as RelationSortOrderType,
        },
      },
      capital: {
        type: "single" as RelationDataType,
      },
    },
  },
};

const userRelations = {
  livedCities: {
    optional: false,
    schemaName: "city",
    type: "multiple",
    sort: {
      field: "_id",
      order: "desc",
    },
    relatedRelations: {
      users: {
        type: "multiple",
        limit: 50,
        sort: {
          field: "_id",
          order: "desc",
        },
      },
    },
  },

  country: {
    optional: false,
    schemaName: "country",
    type: "single",
    relatedRelations: {
      users: {
        type: "multiple",
        limit: 50,
        sort: {
          field: "_id",
          order: "desc",
        },
      },
    },
  },
};

Screen-Shot-1402-10-28-at-10 04 16 As we said earlier, the data created based on this country will be useless. Here the cities and users created based on this country become useless. Pay attention to the following code:

const deleteCountryValidator = () => {
  return object({
    set: object({
      _id: string(),
    }),
    get: object({
      success: optional(enums([0, 1])),
    }),
  });
};
const deleteCountry: ActFn = async (body) => {
  const {
    set: { _id },
    get,
  } = body.details;
  return await countries.deleteOne({
    filter: { _id: new ObjectId(_id) },
  });
};
coreApp.acts.setAct({
  schema: "country",
  actName: "deleteCountry",
  validator: deleteCountryValidator(),
  fn: deleteCountry,
});

By adding the above code and running the software and sending a request to delete a country, and finally if that country has a city or user, we will encounter the following error:

{
  body: {
    message: please clear below relations status before deletion:  [ {  schemaName:  country,   type:  single,   optional:  false,   fieldName:  country,   collection:  city,   doc:  {   _id:  65a3d213e18957d8c176ffb4,    name:  Hamedan,    population:  900000,    abb:  HM,    country:  {    _id:  65a3d213e18957d8c176ffb2,     name:  Islamic Republic Of Iran,     population:  89000000,     abb:  IR   },    users:  [    {     _id:  65a3d213e18957d8c176ffc0,      name:  Mohammad Sheida,      age:  20    },     {     _id:  65a3d213e18957d8c176ffbf,      name:  Elham Afshar,      age:  25    },     {     _id:  65a3d213e18957d8c176ffbd,      name:  Saeid Ghal,      age:  27    },     {     _id:  65a3d213e18957d8c176ffbc,      name:  Ehsan Akefi,      age:  20    },     {     _id:  65a3d213e18957d8c176ffbb,      name:  Amir Meyari,      age:  30    }   ]  } },  {  schemaName:  country,   type:  single,   optional:  false,   fieldName:  country,   collection:  user,   doc:  {   _id:  65a3d213e18957d8c176ffb7,    name:  Syd Amir,    age:  36,    livedCities:  [    {     _id:  65a3d213e18957d8c176ffb4,      name:  Hamedan,      population:  900000,      abb:  HM    },     {     _id:  65a3d213e18957d8c176ffb5,      name:  Tehran,      population:  1000000,      abb:  TH    }   ],    country:  {    _id:  65a3d213e18957d8c176ffb2,     name:  Islamic Republic Of Iran,     population:  89000000,     abb:  IR   }  } }]
  },
  success: false
}

We have two ways:

  • Delete all these documents related to this country one by one.
  • Set the hardCascade option to true in the deleteOne function. We change the above code as follows:
return await countries.deleteOne({
  filter: { _id: new ObjectId(_id) },
  hardCascade: true,
});

This will cause all the dependent documents and the dependent documents of these dependent documents to be deleted recursively.

You can find full example here and test the deleteOne method in local computer.

bfore execut maincountrydeleteCountry: delete-country-before

executing maincountrydeleteCountry: deleteing-country

after execut maincountrydeleteCountry: delete-country-after

Add E2E Test

Like before, for adding deleteCountry request to E2E section you should click on the e2e button (like bottom picture) to add your request to E2E section.

e2e sequence

Then, in the E2E section and deleteCountry sequence, you should replace the country id that you set capture in own sequence with default country id. default country id in deleteCountry sequence is like below picture.

e2e sequence

The replaced country id is like below picture.

e2e sequence