insertMany functions
Another surprise of Lesan is the use of insertMany while all relationships can be embedded correctly.
Consider the following example:
const addCitiesValidator = () => {
return object({
set: object({
multiCities: array(object(countryCityPure)),
country: objectIdValidation,
}),
get: coreApp.schemas.selectStruct("city", 1),
});
};
const addCities: ActFn = async (body) => {
const { country, multiCities } = body.details.set;
return await cities.insertMany({
docs: multiCities,
projection: body.details.get,
relations: {
country: {
_ids: new ObjectId(country),
relatedRelations: {
cities: true,
citiesByPopulation: true,
capital: false,
},
},
},
});
};
coreApp.acts.setAct({
schema: "city",
actName: "addCities",
validator: addCitiesValidator(),
fn: addCities,
});
There are two important points in the above code:
-
The
multiCitiesinput is anarrayofpurecityfieldobjects. Therefore, it must have the following value:"multiCities": [ { "name": "Beirout", "abb": "BI", "population": 20000000 }, { "name": "Baalbak", "abb": "BA", "population": 850000 } ]The beautiful thing here is that before the
addCitiesfunction is executed, all data, includingmultiCities, isvalidated. This feature allows us tovalidatethewrongdatabeforesending anycommandto thedatabase. -
The second point is that we explicitly set the
capitalrelation in the cityrelatedRelationtofalse. Because we do not know whichcityis going to be chosen as thecapital. In general,one-to-onerelations ininsertManyshould always befalsebecause they destroy the concept ofinsertManyand cause itsrelatedRelationsto be updatedoncefor every new document that is added, which is usually wrong.
Pay attention that all changes are sent to the database with an aggregation pipeline.
You can find full example here and test the insertMany method in local computer.
bfore execut main → city → addCities:
executing main → city → addCities:
after execut main → city → addCities:
Let us use insertMany to add users:
const addUsersValidator = () => {
return object({
set: object({
multiUsers: array(object()),
country: objectIdValidation,
livedCities: array(objectIdValidation),
lovedCity: objectIdValidation,
}),
get: coreApp.schemas.selectStruct("user", 1),
});
};
const addUsers: ActFn = async (body) => {
const { country, multiUsers, livedCities, lovedCity } = body.details.set;
const obIdLivedCities = livedCities.map((lp: string) => new ObjectId(lp));
return await users.insertMany({
docs: multiUsers,
projection: body.details.get,
relations: {
country: {
_ids: new ObjectId(country),
relatedRelations: {
users: true,
},
},
livedCities: {
_ids: obIdLivedCities,
relatedRelations: {
users: true,
},
},
mostLovedCity: {
_ids: new ObjectId(lovedCity),
relatedRelations: {
lovedByUser: true,
},
},
},
});
};
coreApp.acts.setAct({
schema: "user",
actName: "addUsers",
validator: addUsersValidator(),
fn: addUsers,
});
In the code above, there are almost all types of relationships that we can use in insertMany.
-
There is a
one-to-manyrelationship betweenusersandcountries, that is, thecountryfield receives anID, and after finding the relevantcountry, itspurefields are stored in theuser. On thecountryside, in two multiple lists, the user is stored once with ID sorted from last to first(usersfield) and once with age sorted from oldest to youngest(usersByAge). -
Also,
usershave amany-to-manyrelationship with thecitiesthey have lived in and receive a set of cityIDs, and after finding thosecities, thepurefields of each one are stored in an array calledlivedCities.On thecityside, thepurefields of the enteredusersare stored in theusersfield for eachcity. -
The
userhas anotherrelationshipwith thecity, which is aone-to-manyrelationship. In this way, theusersaves thecityhe likes the most in themostLovedCityfield. And on thecityside, the list of enteredusersis stored in the field oflovedByUser.
bfore execut main → user → addUsers:
executing main → user → addUsers:
after execut main → user → addUsers:
Pay attention that all changes are sent to the database with an aggregation pipeline.
You can find full example here and test the insertMany method in local computer.
The implementation of insertMany for the country is also very simple because no relationship is needed to create the countries, we will leave the implementation of this part of the code to you.
If you want to see a real insertMany code, you can see the code implemented for the benchmark here.
The interesting thing is that due to the correct definition of the relationship in Lesan, the implementation of the benchmark code with insertMany was very simple, while this task was a bit complicated in the rest of the platforms.
Also, the time spent for entering data in Lesan is interesting, because this time is very short due to insertMany.