Even though NoSQL is very fast, its complexities are very troublesome for large-scale projects. On the other hand, GraphQL shines in client-server connectivity but it has several weaknesses and is somewhat complex, adding another layer of complexity to the project. That’s why we created LESAN.
This video is an introductory tutorial on Lesan framework in Farsi language.
We use this formula to calculate the difference : (B - A) ÷ A * 100
As you see on the chart:
1168%
faster than the prisma-express-rest
. Which uses postgres
as a database.1417%
faster than the prisma-express-graphql
. Which uses postgres
as a database.4435%
faster than the mongoose-express-rest
(Note that we did not sort in this query)72289%
faster than the mongo-express-rest
(Note that we did not sort in this query)298971%
faster than the mongoose-express-rest
(used sortby)Maybe we created the most performant framework in the world! see more detailed benchmark
Create a file called mod.ts
and paste the code below into it:
import {
ActFn,
Document,
Filter,
lesan,
MongoClient,
number,
object,
ObjectId,
optional,
size,
string,
} from "https://deno.land/x/lesan@vx.x.x/mod.ts"; // Please replace `x.x.x` with the latest version in [releases](https://github.com/MiaadTeam/lesan/releases)
const coreApp = lesan();
const client = await new MongoClient("mongodb://127.0.0.1:27017/").connect();
const db = client.db("civil");
coreApp.odm.setDb(db);
// ================== MODEL SECTION ==================
// ------------------ Country Model ------------------
const countryPure = {
name: string(),
population: number(),
abb: string(),
};
const countryRelations = {};
const countries = coreApp.odm.newModel(
"country",
countryPure,
countryRelations
);
// ------------------ User Model ------------------
const userPure = {
name: string(),
age: number(),
};
const users = coreApp.odm.newModel("user", userPure, {
country: {
optional: false,
schemaName: "country",
type: "single",
relatedRelations: {
users: {
type: "multiple",
limit: 50,
sort: {
field: "_id",
order: "desc",
},
},
},
},
});
// ================== FUNCTIONS SECTION ==================
// ------------------ Country Founctions ------------------
// ------------------ Add Country ------------------
const addCountryValidator = () => {
return object({
set: object(countryPure),
get: coreApp.schemas.selectStruct("country", { users: 1 }),
});
};
const addCountry: ActFn = async (body) => {
const { name, population, abb } = body.details.set;
return await countries.insertOne({
doc: {
name,
population,
abb,
},
projection: body.details.get,
});
};
coreApp.acts.setAct({
schema: "country",
actName: "addCountry",
validator: addCountryValidator(),
fn: addCountry,
});
// ------------------ Get Countries ------------------
const getCountriesValidator = () => {
return object({
set: object({
page: number(),
limit: number(),
}),
get: coreApp.schemas.selectStruct("country", 1),
});
};
const getCountries: ActFn = async (body) => {
let {
set: { page, limit },
get,
} = body.details;
page = page || 1;
limit = limit || 50;
const skip = limit * (page - 1);
return await countries
.find({ projection: get, filters: {} })
.skip(skip)
.limit(limit)
.toArray();
};
coreApp.acts.setAct({
schema: "country",
actName: "getCountries",
validator: getCountriesValidator(),
fn: getCountries,
});
// ------------------ User Founctions ------------------
// --------------------- Add User ----------------------
const addUserValidator = () => {
return object({
set: object({
...userPure,
country: string(),
}),
get: coreApp.schemas.selectStruct("user", 1),
});
};
const addUser: ActFn = async (body) => {
const { country, name, age } = body.details.set;
return await users.insertOne({
doc: { name, age },
projection: body.details.get,
relations: {
country: {
_ids: new ObjectId(country),
relatedRelations: {
users: true,
},
},
},
});
};
coreApp.acts.setAct({
schema: "user",
actName: "addUser",
validator: addUserValidator(),
fn: addUser,
});
// --------------------- Get Users ----------------------
const getUsersValidator = () => {
return object({
set: object({
page: number(),
take: number(),
countryId: optional(size(string(), 24)),
}),
get: coreApp.schemas.selectStruct("user", { country: 1 }),
});
};
const getUsers: ActFn = async (body) => {
let {
set: { page, limit, countryId },
get,
} = body.details;
page = page || 1;
limit = limit || 50;
const skip = limit * (page - 1);
const filters: Filter<Document> = {};
countryId && (filters["country._id"] = new ObjectId(countryId));
return await users
.find({ projection: get, filters })
.skip(skip)
.limit(limit)
.toArray();
};
coreApp.acts.setAct({
schema: "user",
actName: "getUsers",
validator: getUsersValidator(),
fn: getUsers,
});
// ================== RUM SECTION ==================
coreApp.runServer({ port: 1366, typeGeneration: false, playground: true });
Please replace
x.x.x
in the import link with the latest version in releases
Now run this command in the terminal:
deno run -A mod.ts
You should see this messsage:
HTTP webserver running.
please send a post request to http://localhost:1366/lesan
you can visit playground on http://localhost:1366/playground
Listening on http://localhost:1366/
Now you can visit the playground at http://localhost:1366/playground
and send requests to the server for addCountry
, addUser
, and getUsers
.
alternativly you can send post request to http://localhost:1366/lesan
with postman
include the following in JSON format inside the body in order to retrieve the desired data:
{
"service": "main",
"model": "country",
"act": "addCountry",
"details": {
"set": {
"name": "Iran",
"population": 85000000,
"abb": "IR"
},
"get": {
"_id": 1,
"name": 1,
"population": 1,
"abb": 1
}
}
}
We handle all relationships between the data and embed
everything. You can also control the level of penetration into the action get
depth. On the client-side
, you can describe what you want and get back exactly what you described.
Mehrshad Cheshm Khavari |
Mahdi Ramezani |
Alireza Safaierad |
ali davodi |
sorena ganji |
Node Master |
Alireza Safaierad |
Erfan Asadi |