addRelation function
Update Many to Many Relation
Pay attention to the following code:
const addUserLivedCityValidator = () => {
return object({
set: object({
_id: objectIdValidation,
livedCities: array(objectIdValidation),
}),
get: coreApp.schemas.selectStruct("user", 1),
});
};
const addUserLivedCity: ActFn = async (body) => {
const { livedCities, _id } = body.details.set;
const obIdLivedCities = livedCities.map((lc: string) => new ObjectId(lc));
return await users.addRelation({
filters: { _id: new ObjectId(_id) },
projection: body.details.get,
relations: {
livedCities: {
_ids: obIdLivedCities,
relatedRelations: {
users: true,
},
},
},
});
};
coreApp.acts.setAct({
schema: "user",
actName: "addUserLivedCities",
validator: addUserLivedCityValidator(),
fn: addUserLivedCity,
});
In addition to the functions insert, update, delete, find, etc., for each model in the Lesan, there are two other functions in addition to MongoDB functions, named addRelation and removeRelation, which are prepared for managing relationships. In the code above, the addRelation function is used. This function receives an object input with the following keys:
- A
filterkey that receives MongoDB findOne filter and finds only one document to change its relationships. - The
relationskey receives an object from the relations of this model. We talk about the relation input here - The
projectionkey is used to receive written data. Also we talk aboutprojectionkey here - And another key called
replace, which is not used here, and receives a boolean value offalseortrue. We will talk about this key in the next step.
In the function above, we add one or more cities to the set of cities where a user has lived. In fact, in the validation function, the user ID is received along with an array of city IDs, and in the Act function, we convert the array of city IDs into an array of object IDs and give it to the addRelation function along with the user ID. As a result, on the user side, one or more cities are added to the livedCities array, and on the city side, this user is added to each of the cities whose IDs have been sent.
Run the code
Since all the code is getting bigger and bigger, we put it on GitHub, you can see and download it here.
By running the codes and going to the playground, you can see and test the functions added to the user.
before execute main → country → addUserLivedCities:
executing
main → country → addUserLivedCities:
after execute
main → country → addUserLivedCities:
Add E2E Test
For adding addUserLivedCities request to E2E test section, you should click on the E2E button, like bottom picture.
Then, you should click on the Add Capture button in the addCity sequence and fill the inputs like below picture. in my example i add Mashhad city.
After that, you should change the default user id add lived cities id with capture that you set in the past. the default id is like below picture.
And replace the capture you set in the past like below picture.
Update One to Many Relation
What if in one of these sides our field is an object instead of an array (In fact, the type of relationship is one-to-many or many-to-one.)? For example, let's change the country on the user side.
Look at code below:
const addUserCountryValidator = () => {
return object({
set: object({
_id: objectIdValidation,
country: objectIdValidation,
}),
get: coreApp.schemas.selectStruct("user", 1),
});
};
const addUserCountry: ActFn = async (body) => {
const { country, _id } = body.details.set;
return await users.addRelation({
_id: new ObjectId(_id),
projection: body.details.get,
relations: {
country: {
_ids: new ObjectId(country),
relatedRelations: {
users: true,
},
},
},
replace: true,
});
};
coreApp.acts.setAct({
schema: "user",
actName: "addUserCountry",
validator: addUserCountryValidator(),
fn: addUserCountry,
});
In the code above, we get the ID of a user along with the ID of a country and give it to the addRelation function. Please note that the country is not optional in the user model and is defined with a single type. Therefore, if we change the country of a user, we must first find and delete this user in the country he was in before, then add the new country to the user and the user to the new country. For this reason, we have given the value true to the replace key in the addRelation entry. In this function, if we set replace equal to false or do not enter it, no operation will be performed and we will get an error.
Steps to add a country to a user
The bottom line is a bit complicated but has its own charm.
To change the country in a user, we must do the following steps:
- Find the user
- Finding the user's old country
- Find the user's new country
- Checking whether this user was part of the list of users in the old country or not (users may exist in several fields in one country, for example, the list of users who are the oldest or the youngest).
- Creating a
commandto delete the user from the old country (from all the lists in which the user was found). - If this list has a certain limit and we have reached the end of this limit, we need to find the next user to be added to this list. For this purpose, we must do the following steps:
- Find out how to save this list.
- Finding the next 3 users who can be added to this list (because it is possible to find either the same user that we intend to delete from the list, or the end user of this list).
- Creating an
commandto add these 3 users to the end of this list. - Creating a
commandto unify this list. - Creating a
commandto delete the current user from this list. - Creating a sorting
commandfor this list according to the method we mentioned in the initial settings of relationships. - Creating an
commandto limit this list to the number that we said in the initial settings of relationships.
- Creating an
commandto add this user to all user lists in the new country. (Here we also have to check if this list has limit or not and if so, this user can be added to this list or not, which we have to do step #6 for each list in the new country). - Execution of all the
commandswe have created so far. - Execution of the
commandto insert the new country instead of the old country in this user.
Run the code
Since all the code is getting bigger and bigger, we put it on GitHub, you can see and download it here.
By running the codes and going to the playground, you can see and test the functions added to the user.
before execute main → country → addUserCountry:
executing
main → country → addUserCountry:
before execute
main → country → addUserCountry:
Add E2E Test
For adding addUserCountry request to E2E test section, you should click on the E2E button, like bottom picture.
Then, in the E2E section and addUserCountry sequence you should replace the user id and country id that you set capture in own sequence with default user id and country id. default user and country id is like below picture.
The replaced user and country id is like below picture.