Реализация репозитория для работы с базами данных
|
|
2 лет назад | |
|---|---|---|
| .husky | 2 лет назад | |
| docs | 2 лет назад | |
| src | 2 лет назад | |
| .c8rc | 2 лет назад | |
| .commitlintrc | 2 лет назад | |
| .editorconfig | 2 лет назад | |
| .eslintignore | 2 лет назад | |
| .eslintrc.cjs | 2 лет назад | |
| .gitignore | 2 лет назад | |
| .mocharc.cjs | 2 лет назад | |
| .prettierrc | 2 лет назад | |
| LICENSE | 2 лет назад | |
| README.md | 2 лет назад | |
| mocha.setup.js | 2 лет назад | |
| package.json | 2 лет назад | |
| tsconfig.json | 2 лет назад | |
| typedoc.json | 2 лет назад |
Модуль для работы с базами данных для Node.js
npm install @e22m4u/js-repository
Опционально устанавливаем адаптер.
| описание | |
|---|---|
memory |
виртуальная база в памяти процесса (не требует установки) |
mongodb |
MongoDB - система управления NoSQL базами (установка) |
Определение источника данных, модели и добавление нового документа в коллекцию.
import {Schema} from '@e22m4u/js-repository';
import {DataType} from '@e22m4u/js-repository';
// создание экземпляра Schema
const schema = new Schema();
// определение источника "myMemory"
schema.defineDatasource({
name: 'myMemory', // название нового источника
adapter: 'memory', // выбранный адаптер
});
// определение модели "country"
schema.defineModel({
name: 'country', // название новой модели
datasource: 'myMemory', // выбранный источник
properties: { // свойства модели
name: DataType.STRING, // тип "string"
population: DataType.NUMBER, // тип "number"
},
})
// получение репозитория для модели "country"
const countryRep = schema.getRepository('country');
// добавление нового документа в коллекцию "country"
const country = await countryRep.create({
name: 'Russia',
population: 143400000,
});
// вывод результата
console.log(country);
// {
// "id": 1,
// "name": "Russia",
// "population": 143400000,
// }
Экземпляр класса Schema хранит определения источников
данных и моделей.
Методы
defineDatasource(datasourceDef: object): this -
добавить источникdefineModel(modelDef: object): this - добавить
модельgetRepository(modelName: string): Repository - получить
репозиторийПримеры
Импорт класса и создание экземпляра схемы.
import {Schema} from '@e22m4u/js-repository';
const schema = new Schema();
Определение нового источника.
schema.defineDatasource({
name: 'myMemory', // название нового источника
adapter: 'memory', // выбранный адаптер
});
Определение новой модели.
schema.defineModel({
name: 'product', // название новой модели
datasource: 'myMemory', // выбранный источник
properties: { // свойства модели
name: DataType.STRING,
weight: DataType.NUMBER,
},
});
Получение репозитория по названию модели.
const productRep = schema.getRepository('product');
Источник хранит название выбранного адаптера и его настройки.
Определить новый источник можно методом defineDatasource
экземпляра схемы.
Параметры
name: string уникальное названиеadapter: string выбранный адаптерПримеры
Определение нового источника.
schema.defineDatasource({
name: 'myMemory', // название нового источника
adapter: 'memory', // выбранный адаптер
});
Передача дополнительных параметров адаптера.
schema.defineDatasource({
name: 'myMongodb',
adapter: 'mongodb',
// параметры адаптера "mongodb"
host: '127.0.0.1',
port: 27017,
database: 'myDatabase',
});
Описывает структуру документа коллекции и связи к другим моделям.
Определить новую модель можно методом defineModel
экземпляра схемы.
Параметры
name: string название модели (обязательно)base: string название наследуемой моделиtableName: string название коллекции в базеdatasource: string выбранный источник данныхproperties: object определения свойств (см. Свойства)relations: object определения связей (см. Связи)Примеры
Определение модели со свойствами указанного типа.
schema.defineModel({
name: 'user', // название новой модели
properties: { // свойства модели
name: DataType.STRING,
age: DataType.NUMBER,
},
});
Параметр properties находится в составе модели и
принимает объект, ключи которого являются свойствами этой модели, а
значением тип свойства или объект с дополнительными параметрами.
Тип данных
DataType.ANY разрешено любое значениеDataType.STRING только значение типа
stringDataType.NUMBER только значение типа
numberDataType.BOOLEAN только значение типа
booleanDataType.ARRAY только значение типа
arrayDataType.OBJECT только значение типа
objectПараметры
type: string тип допустимого значения
(обязательно)itemType: string тип элемента массива (для
type: 'array')model: string модель объекта (для
type: 'object')primaryKey: boolean объявить свойство первичным
ключомcolumnName: string переопределение названия
колонкиcolumnType: string тип колонки (определяется
адаптером)required: boolean объявить свойство обязательнымdefault: any значение по умолчаниюПримеры
Краткое определение свойств модели.
schema.defineModel({
name: 'city',
properties: { // свойства модели
name: DataType.STRING, // тип свойства "string"
population: DataType.NUMBER, // тип свойства "number"
},
});
Расширенное определение свойств модели.
schema.defineModel({
name: 'city',
properties: { // свойства модели
name: {
type: DataType.STRING, // тип свойства "string" (обязательно)
required: true, // исключение значений undefined и null
},
population: {
type: DataType.NUMBER, // тип свойства "number" (обязательно)
default: 0, // значение по умолчанию
},
},
});
Фабричное значение по умолчанию. Возвращаемое значение функции будет определено в момент записи документа.
schema.defineModel({
name: 'article',
properties: { // свойства модели
tags: {
type: DataType.ARRAY, // тип свойства "array" (обязательно)
itemType: DataType.STRING, // тип элемента "string"
default: () => [], // фабричное значение
},
createdAt: {
type: DataType.STRING, // тип свойства "string" (обязательно)
default: () => new Date().toISOString(), // фабричное значение
},
},
});
Выполняет операции чтения и записи документов определенной модели.
Получить репозиторий можно методом getRepository экземпляра
схемы.
Методы
create(data, filter = undefined) добавить новый
документreplaceById(id, data, filter = undefined) заменить весь
документpatchById(id, data, filter = undefined) частично
обновить документpatch(data, where = undefined) обновить все документы
или по условиюfind(filter = undefined) найти все документы или по
условиюfindOne(filter = undefined) найти первый документ или
по условиюfindById(id, filter = undefined) найти документ по
идентификаторуdelete(where = undefined) удалить все документы или по
условиюdeleteById(id) удалить документ по идентификаторуexists(id) проверить существование по
идентификаторуcount(where = undefined) подсчет всех документов или по
условиюАргументы
id: number|string идентификатор (первичный ключ)data: object объект отражающий состав документаwhere: object параметры выборки (см. Фильтрация)filter: object параметры возвращаемого результата (см.
Фильтрация)Примеры
Получение репозитория по названию модели.
const countryRep = schema.getRepository('country');
Добавление нового документа в коллекцию.
const res = await countryRep.create({
name: 'Russia',
population: 143400000,
});
console.log(res);
// {
// "id": 1,
// "name": "Russia",
// "population": 143400000,
// }
Поиск документа по идентификатору.
const res = await countryRep.findById(1);
console.log(res);
// {
// "id": 1,
// "name": "Russia",
// "population": 143400000,
// }
Удаление документа по идентификатору.
const res = await countryRep.deleteById(1);
console.log(res); // true
Некоторые методы репозитория принимают объект настроек влияющий на
возвращаемый результат. Максимально широкий набор таких настроек имеет
первый параметр метода find, где ожидается объект
содержащий набор опций указанных ниже.
where: object объект выборкиorder: string[] указание порядкаlimit: number ограничение количества документовskip: number пропуск документовfields: string[] выбор необходимых свойств моделиinclude: object включение связанных данных в
результатПараметр принимает объект с условиями выборки и поддерживает широкий набор операторов сравнения.
{foo: 'bar'} поиск по значению свойства
foo
{foo: {eq: 'bar'}} оператор равенства eq
{foo: {neq: 'bar'}} оператор неравенства
neq
{foo: {gt: 5}} оператор "больше" gt
{foo: {lt: 10}} оператор "меньше" lt
{foo: {gte: 5}} оператор "больше или равно"
gte
{foo: {lte: 10}} оператор "меньше или равно"
lte
{foo: {inq: ['bar', 'baz']}} равенство одного из значений
inq
{foo: {nin: ['bar', 'baz']}} исключение значений массива
nin
{foo: {between: [5, 10]}} оператор диапазона
between
{foo: {exists: true}} оператор наличия значения
exists
{foo: {like: 'bar'}} оператор поиска подстроки
like
{foo: {ilike: 'BaR'}} регистронезависимая версия
ilike
{foo: {nlike: 'bar'}} оператор исключения подстроки
nlike
{foo: {nilike: 'BaR'}} регистронезависимая версия
nilike
{foo: {regexp: 'ba.+'}} оператор регулярного выражения
regexp
{foo: {regexp: 'ba.+', flags: 'i'}} флаги регулярного
выражения
i. Условия можно объединять операторами and,
or и nor.
Примеры
Применение условий выборки при подсчете документов.
const res = await rep.count({
authorId: 251,
publishedAt: {
lte: '2023-12-02T14:00:00.000Z',
},
});
Применение оператора or при удалении документов.
const res = await rep.delete({
or: [
{draft: true},
{title: {like: 'draft'}},
],
});
Параметр упорядочивает выборку по указанным свойствам модели.
Обратное направление порядка можно задать постфиксом DESC в
названии свойства.
Примеры
Упорядочить по полю createdAt
const res = await rep.find({
order: 'createdAt',
});
Упорядочить по полю createdAt в обратном порядке.
const res = await rep.find({
order: 'createdAt DESC',
});
Упорядочить по нескольким свойствам в разных направлениях.
const res = await rep.find({
order: [
'title',
'price ASC',
'featured DESC',
],
});
i. Направление порядка ASC указывать
необязательно.
Параметр relations находится в составе определения
модели и принимает объект, ключ которого является названием связи, а
значением объект с параметрами.
Параметры
type: string тип связиmodel: string название целевой моделиforeignKey: string свойство текущей модели для
идентификатора целиpolymorphic: boolean|string объявить связь
полиморфной*discriminator: string свойство текущей модели для
названия целевой*i. Полиморфный режим позволяет динамически определять целевую модель по ее названию, которое хранит документ в свойстве-дискриминаторе.
Тип связи
belongsTo - текущая модель содержит свойство для
идентификатора целиhasOne - обратная сторона belongsTo по
принципу "один к одному"hasMany - обратная сторона belongsTo по
принципу "один ко многим"referencesMany - документ содержит массив с
идентификаторами целевой моделиПримеры
Объявление связи belongsTo
schema.defineModel({
name: 'user',
relations: {
role: { // название связи
type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
model: 'role', // название целевой модели
foreignKey: 'roleId', // свойство для идентификатора (необязательно)
},
},
});
Объявление связи hasMany
schema.defineModel({
name: 'role',
relations: {
users: { // название связи
type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
model: 'user', // название целевой модели
foreignKey: 'roleId', // свойство целевой модели для идентификатора
},
},
});
Объявление связи referencesMany
schema.defineModel({
name: 'article',
relations: {
categories: { // название связи
type: RelationType.REFERENCES_MANY, // связь через массив идентификаторов
model: 'category', // название целевой модели
foreignKey: 'categoryIds', // свойство для идентификаторов (необязательно)
},
},
});
Полиморфная версия belongsTo
schema.defineModel({
name: 'file',
relations: {
reference: { // название связи
type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
// cогласно названию связи "reference", полиморфный режим позволяет
// хранить название целевой модели в свойстве "referenceType",
// а идентификатор целевого документа в "referenceId"
polymorphic: true,
},
},
});
Полиморфная версия belongsTo с указанием свойств.
schema.defineModel({
name: 'file',
relations: {
reference: { // название связи
type: RelationType.BELONGS_TO, // текущая модель ссылается на целевую
polymorphic: true, // название целевой модели хранит дискриминатор
foreignKey: 'referenceId', // свойство для идентификатора цели
discriminator: 'referenceType', // свойство для названия целевой модели
},
},
})
Полиморфная версия hasMany с указанием названия связи
целевой модели.
schema.defineModel({
name: 'letter',
relations: {
attachments: { // название связи
type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
model: 'file', // название целевой модели
polymorphic: 'reference', // название полиморфной связи целевой модели
},
},
})
Полиморфная версия hasMany с указанием свойств целевой
модели.
schema.defineModel({
name: 'letter',
relations: {
attachments: { // название связи
type: RelationType.HAS_MANY, // целевая модель ссылается на текущую
model: 'file', // название целевой модели
polymorphic: true, // название текущей модели находится в дискриминаторе
foreignKey: 'referenceId', // свойство целевой модели для идентификатора
discriminator: 'referenceType', // свойство целевой модели для названия текущей
},
},
})
npm run test
MIT