@e22m4u/js-repository 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +299 -70
- package/dist/cjs/index.cjs +197 -139
- package/package.json +2 -2
- package/src/adapter/builtin/memory-adapter.spec.js +2 -2
- package/src/filter/filter-clause.d.ts +4 -4
- package/src/filter/operator-clause-tool.d.ts +2 -1
- package/src/filter/operator-clause-tool.js +92 -104
- package/src/filter/operator-clause-tool.spec.js +560 -315
- package/src/filter/where-clause-tool.js +39 -41
- package/src/filter/where-clause-tool.spec.js +123 -13
- package/src/repository/repository.d.ts +4 -4
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/utils/like-to-regexp.d.ts +14 -0
- package/src/utils/like-to-regexp.js +57 -0
- package/src/utils/like-to-regexp.spec.js +143 -0
package/README.md
CHANGED
|
@@ -1050,27 +1050,14 @@ console.log(res); // true
|
|
|
1050
1050
|
- `fields: string|string[]` выбор необходимых свойств модели;
|
|
1051
1051
|
- `include: object` включение связанных данных в результат;
|
|
1052
1052
|
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
Объект фильтрации позволяет комбинировать различные опции для построения
|
|
1056
|
-
сложных запросов. Представим, что нам нужно выбрать из коллекции новости
|
|
1057
|
-
для отображения на сайте по следующему набору критериев:
|
|
1058
|
-
|
|
1059
|
-
- Заголовок должен содержать слово «Moscow» без учета регистра.
|
|
1060
|
-
- Дата публикации должна быть не ранее 15 октября 2025 года.
|
|
1061
|
-
- Новость должна содержать один из тегов «world» или «politic».
|
|
1062
|
-
- Новость не должна быть скрытой `hidden: false`.
|
|
1063
|
-
- Результат должен быть отсортирован по дате публикации.
|
|
1064
|
-
- Нужно пропустить первые 24 записи и выбрать следующие 12.
|
|
1065
|
-
- Выборка должна включать только поля `title`, `annotation` и `body`.
|
|
1066
|
-
- К каждой новости добавить связанные данные `author` и `category`.
|
|
1053
|
+
**Пример**
|
|
1067
1054
|
|
|
1068
1055
|
```js
|
|
1069
1056
|
// для запроса используется метод репозитория "find"
|
|
1070
1057
|
// с передачей объекта фильтрации первым аргументом
|
|
1071
1058
|
const news = await newsRepository.find({
|
|
1072
1059
|
where: {
|
|
1073
|
-
title: {
|
|
1060
|
+
title: {like: '%Moscow%'},
|
|
1074
1061
|
publishedAt: {gte: '2025-10-15T00:00:00.000Z'},
|
|
1075
1062
|
tags: {inq: ['world', 'politic']},
|
|
1076
1063
|
hidden: false,
|
|
@@ -1083,82 +1070,324 @@ const news = await newsRepository.find({
|
|
|
1083
1070
|
})
|
|
1084
1071
|
```
|
|
1085
1072
|
|
|
1086
|
-
|
|
1073
|
+
### where
|
|
1074
|
+
|
|
1075
|
+
Параметр принимает объект с условиями выборки и поддерживает следующий набор
|
|
1076
|
+
операторов сравнения.
|
|
1087
1077
|
|
|
1088
|
-
-
|
|
1089
|
-
-
|
|
1090
|
-
-
|
|
1091
|
-
-
|
|
1092
|
-
-
|
|
1078
|
+
- [Поиск по значению](#поиск-по-значению-сокращенная-форма)
|
|
1079
|
+
- [`eq`](#eq-строгое-равенство) (строгое равенство)
|
|
1080
|
+
- [`neq`](#neq-неравенство) (неравенство)
|
|
1081
|
+
- [`gt`](#gt-больше-чем) (больше чем)
|
|
1082
|
+
- [`lt`](#lt-меньше-чем) (меньше чем)
|
|
1083
|
+
- [`gte`](#gte-больше-или-равно) (больше или равно)
|
|
1084
|
+
- [`lte`](#lte-меньше-или-равно) (меньше или равно)
|
|
1085
|
+
- [`inq`](#inq-в-списке) (в списке)
|
|
1086
|
+
- [`nin`](#nin-не-в-списке) (не в списке)
|
|
1087
|
+
- [`between`](#between-диапазон) (диапазон)
|
|
1088
|
+
- [`exists`](#exists-наличие-свойства) (наличие свойства)
|
|
1089
|
+
- [`like`](#like-шаблон) (шаблон)
|
|
1090
|
+
- [`nlike`](#nlike-исключающий-шаблон) (исключающий шаблон)
|
|
1091
|
+
- [`ilike`](#ilike-регистронезависимый-шаблон) (регистронезависимый шаблон)
|
|
1092
|
+
- [`nilike`](#nilike-регистронезависимый-шаблон-исключения) (регистронезависимый шаблон исключения)
|
|
1093
|
+
- [`regexp`](#regexp-регулярное-выражение) (регулярное выражение)
|
|
1094
|
+
|
|
1095
|
+
Условия можно объединять логическими операторами:
|
|
1096
|
+
|
|
1097
|
+
- [`and`](#and-логическое-и) (логическое И)
|
|
1098
|
+
- [`or`](#or-логическое-или) (логическое ИЛИ)
|
|
1099
|
+
|
|
1100
|
+
#### Поиск по значению (сокращенная форма)
|
|
1101
|
+
|
|
1102
|
+
Находит документы, у которых значение указанного свойства в точности равно
|
|
1103
|
+
переданному значению. Это сокращенная запись для оператора `{eq: ...}`.
|
|
1093
1104
|
|
|
1094
1105
|
```js
|
|
1095
|
-
//
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
fields: ['username', 'avatarUrl', 'bio'],
|
|
1100
|
-
include: {
|
|
1101
|
-
relation: 'posts',
|
|
1102
|
-
scope: {
|
|
1103
|
-
where: {status: 'published'},
|
|
1104
|
-
order: 'createdAt DESC',
|
|
1105
|
-
limit: 5,
|
|
1106
|
-
fields: ['title', 'createdAt'],
|
|
1107
|
-
include: 'category',
|
|
1108
|
-
},
|
|
1106
|
+
// найдет все документы, где age равен 21
|
|
1107
|
+
const res = await rep.find({
|
|
1108
|
+
where: {
|
|
1109
|
+
age: 21,
|
|
1109
1110
|
},
|
|
1110
1111
|
});
|
|
1111
1112
|
```
|
|
1112
1113
|
|
|
1113
|
-
|
|
1114
|
+
#### `eq` (строгое равенство)
|
|
1114
1115
|
|
|
1115
|
-
|
|
1116
|
-
набор операторов сравнения.
|
|
1117
|
-
|
|
1118
|
-
`{foo: 'bar'}` поиск по значению свойства `foo`
|
|
1119
|
-
`{foo: {eq: 'bar'}}` оператор равенства `eq`
|
|
1120
|
-
`{foo: {neq: 'bar'}}` оператор неравенства `neq`
|
|
1121
|
-
`{foo: {gt: 5}}` оператор "больше" `gt`
|
|
1122
|
-
`{foo: {lt: 10}}` оператор "меньше" `lt`
|
|
1123
|
-
`{foo: {gte: 5}}` оператор "больше или равно" `gte`
|
|
1124
|
-
`{foo: {lte: 10}}` оператор "меньше или равно" `lte`
|
|
1125
|
-
`{foo: {inq: ['bar', 'baz']}}` равенство одного из значений `inq`
|
|
1126
|
-
`{foo: {nin: ['bar', 'baz']}}` исключение значений массива `nin`
|
|
1127
|
-
`{foo: {between: [5, 10]}}` оператор диапазона `between`
|
|
1128
|
-
`{foo: {exists: true}}` оператор наличия значения `exists`
|
|
1129
|
-
`{foo: {like: 'bar'}}` оператор поиска подстроки `like`
|
|
1130
|
-
`{foo: {ilike: 'BaR'}}` регистронезависимая версия `ilike`
|
|
1131
|
-
`{foo: {nlike: 'bar'}}` оператор исключения подстроки `nlike`
|
|
1132
|
-
`{foo: {nilike: 'BaR'}}` регистронезависимая версия `nilike`
|
|
1133
|
-
`{foo: {regexp: '^ba.+'}}` оператор регулярного выражения `regexp`
|
|
1134
|
-
`{foo: {regexp: '^ba.+', flags: 'i'}}` флаги регулярного выражения
|
|
1135
|
-
|
|
1136
|
-
*i. Условия можно объединять операторами `and`, `or` и `nor`.*
|
|
1116
|
+
Находит документы, у которых значение свойства равно указанному.
|
|
1137
1117
|
|
|
1138
|
-
|
|
1118
|
+
```js
|
|
1119
|
+
// найдет все документы, где age равен 21
|
|
1120
|
+
const res = await rep.find({
|
|
1121
|
+
where: {
|
|
1122
|
+
age: {eq: 21},
|
|
1123
|
+
},
|
|
1124
|
+
});
|
|
1125
|
+
```
|
|
1139
1126
|
|
|
1140
|
-
|
|
1127
|
+
#### `neq` (неравенство)
|
|
1128
|
+
|
|
1129
|
+
Находит документы, у которых значение свойства не равно указанному.
|
|
1141
1130
|
|
|
1142
1131
|
```js
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1132
|
+
// найдет все документы, где age не равен 21
|
|
1133
|
+
const res = await rep.find({
|
|
1134
|
+
where: {
|
|
1135
|
+
age: {neq: 21},
|
|
1147
1136
|
},
|
|
1148
1137
|
});
|
|
1149
1138
|
```
|
|
1150
1139
|
|
|
1151
|
-
|
|
1140
|
+
#### `gt` (больше чем)
|
|
1141
|
+
|
|
1142
|
+
Находит документы, у которых значение свойства строго больше указанного.
|
|
1152
1143
|
|
|
1153
1144
|
```js
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1145
|
+
// найдет документы, где age больше 30
|
|
1146
|
+
const res = await rep.find({
|
|
1147
|
+
where: {
|
|
1148
|
+
age: {gt: 30},
|
|
1149
|
+
},
|
|
1159
1150
|
});
|
|
1160
1151
|
```
|
|
1161
1152
|
|
|
1153
|
+
#### `lt` (меньше чем)
|
|
1154
|
+
|
|
1155
|
+
Находит документы, у которых значение свойства строго меньше указанного.
|
|
1156
|
+
|
|
1157
|
+
```js
|
|
1158
|
+
// найдет документы, где age меньше 30
|
|
1159
|
+
const res = await rep.find({
|
|
1160
|
+
where: {
|
|
1161
|
+
age: {lt: 30},
|
|
1162
|
+
},
|
|
1163
|
+
});
|
|
1164
|
+
```
|
|
1165
|
+
|
|
1166
|
+
#### `gte` (больше или равно)
|
|
1167
|
+
|
|
1168
|
+
Находит документы, у которых значение свойства больше или равно указанному.
|
|
1169
|
+
|
|
1170
|
+
```js
|
|
1171
|
+
// найдет документы, где age больше или равен 30
|
|
1172
|
+
const res = await rep.find({
|
|
1173
|
+
where: {
|
|
1174
|
+
age: {gte: 30},
|
|
1175
|
+
},
|
|
1176
|
+
});
|
|
1177
|
+
```
|
|
1178
|
+
|
|
1179
|
+
#### `lte` (меньше или равно)
|
|
1180
|
+
|
|
1181
|
+
Находит документы, у которых значение свойства меньше или равно указанному.
|
|
1182
|
+
|
|
1183
|
+
```js
|
|
1184
|
+
// найдет документы, где age меньше или равен 30
|
|
1185
|
+
const res = await rep.find({
|
|
1186
|
+
where: {
|
|
1187
|
+
age: {lte: 30},
|
|
1188
|
+
},
|
|
1189
|
+
});
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
#### `inq` (в списке)
|
|
1193
|
+
|
|
1194
|
+
Находит документы, у которых значение свойства совпадает с одним из значений
|
|
1195
|
+
в предоставленном массиве.
|
|
1196
|
+
|
|
1197
|
+
```js
|
|
1198
|
+
// найдет документы, где name - 'John' или 'Mary'
|
|
1199
|
+
const res = await rep.find({
|
|
1200
|
+
where: {
|
|
1201
|
+
name: {inq: ['John', 'Mary']},
|
|
1202
|
+
},
|
|
1203
|
+
});
|
|
1204
|
+
```
|
|
1205
|
+
|
|
1206
|
+
#### `nin` (не в списке)
|
|
1207
|
+
|
|
1208
|
+
Находит документы, у которых значение свойства отсутствует в предоставленном
|
|
1209
|
+
массиве.
|
|
1210
|
+
|
|
1211
|
+
```js
|
|
1212
|
+
// найдет все документы, кроме тех, где name - 'John' или 'Mary'
|
|
1213
|
+
const res = await rep.find({
|
|
1214
|
+
where: {
|
|
1215
|
+
name: {nin: ['John', 'Mary']},
|
|
1216
|
+
},
|
|
1217
|
+
});
|
|
1218
|
+
```
|
|
1219
|
+
|
|
1220
|
+
#### `between` (диапазон)
|
|
1221
|
+
|
|
1222
|
+
Находит документы, у которых значение свойства находится в указанном диапазоне
|
|
1223
|
+
(включая границы).
|
|
1224
|
+
|
|
1225
|
+
```js
|
|
1226
|
+
// найдет документы, где age находится в диапазоне от 20 до 30 включительно
|
|
1227
|
+
const res = await rep.find({
|
|
1228
|
+
where: {
|
|
1229
|
+
age: {between: [20, 30]},
|
|
1230
|
+
},
|
|
1231
|
+
});
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
#### `exists` (наличие свойства)
|
|
1235
|
+
|
|
1236
|
+
Проверяет наличие или отсутствие свойства в документе. Не проверяет значение
|
|
1237
|
+
свойства.
|
|
1238
|
+
|
|
1239
|
+
- `true` свойство должно существовать (даже если его значение `null`);
|
|
1240
|
+
- `false` свойство должно отсутствовать;
|
|
1241
|
+
|
|
1242
|
+
```js
|
|
1243
|
+
// найдет документы, у которых есть свойство 'nickname'
|
|
1244
|
+
const res1 = await rep.find({
|
|
1245
|
+
where: {
|
|
1246
|
+
nickname: {exists: true},
|
|
1247
|
+
},
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1250
|
+
// найдет документы, у которых нет свойства 'nickname'
|
|
1251
|
+
const res2 = await rep.find({
|
|
1252
|
+
where: {
|
|
1253
|
+
nickname: {exists: false},
|
|
1254
|
+
},
|
|
1255
|
+
});
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
#### `like` (шаблон)
|
|
1259
|
+
|
|
1260
|
+
Выполняет сопоставление с шаблоном, с учетом регистра (см. [подробнее](#операторы-сопоставления-с-шаблоном)).
|
|
1261
|
+
|
|
1262
|
+
```js
|
|
1263
|
+
// найдет {name: 'John Doe'}, но не {name: 'john doe'}
|
|
1264
|
+
const res = await rep.find({
|
|
1265
|
+
where: {
|
|
1266
|
+
name: {like: 'John%'},
|
|
1267
|
+
},
|
|
1268
|
+
});
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1271
|
+
#### `nlike` (исключающий шаблон)
|
|
1272
|
+
|
|
1273
|
+
Находит документы, которые не соответствуют шаблону, с учетом регистра (см. [подробнее](#операторы-сопоставления-с-шаблоном)).
|
|
1274
|
+
|
|
1275
|
+
```js
|
|
1276
|
+
// найдет все, кроме тех, что начинаются на 'John'
|
|
1277
|
+
const res = await rep.find({
|
|
1278
|
+
where: {
|
|
1279
|
+
name: {nlike: 'John%'},
|
|
1280
|
+
},
|
|
1281
|
+
});
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
#### `ilike` (регистронезависимый шаблон)
|
|
1285
|
+
|
|
1286
|
+
Выполняет сопоставление с шаблоном без учета регистра (см. [подробнее](#операторы-сопоставления-с-шаблоном)).
|
|
1287
|
+
|
|
1288
|
+
```js
|
|
1289
|
+
// найдет {name: 'John Doe'} и {name: 'john doe'}
|
|
1290
|
+
const res = await rep.find({
|
|
1291
|
+
where: {
|
|
1292
|
+
name: {ilike: 'john%'},
|
|
1293
|
+
},
|
|
1294
|
+
});
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
#### `nilike` (регистронезависимый шаблон исключения)
|
|
1298
|
+
|
|
1299
|
+
Находит строки, которые не соответствуют шаблону, без учета регистра (см. [подробнее](#операторы-сопоставления-с-шаблоном)).
|
|
1300
|
+
|
|
1301
|
+
```js
|
|
1302
|
+
// найдет все, кроме тех, что начинаются на 'John' или 'john'
|
|
1303
|
+
const res = await rep.find({
|
|
1304
|
+
where: {
|
|
1305
|
+
name: {nilike: 'john%'},
|
|
1306
|
+
},
|
|
1307
|
+
});
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
#### `regexp` (регулярное выражение)
|
|
1311
|
+
|
|
1312
|
+
Находит документы, у которых значение строкового свойства соответствует
|
|
1313
|
+
указанному регулярному выражению. Может быть передано в виде строки или
|
|
1314
|
+
объекта `RegExp`.
|
|
1315
|
+
|
|
1316
|
+
```js
|
|
1317
|
+
// найдет документы, где name начинается с 'J'
|
|
1318
|
+
const res1 = await rep.find({
|
|
1319
|
+
where: {
|
|
1320
|
+
name: {regexp: '^J'},
|
|
1321
|
+
},
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
// найдет документы, где name начинается с 'J' или 'j' (регистронезависимо)
|
|
1325
|
+
const res2 = await rep.find({
|
|
1326
|
+
where: {
|
|
1327
|
+
name: {regexp: '^j', flags: 'i'},
|
|
1328
|
+
},
|
|
1329
|
+
});
|
|
1330
|
+
```
|
|
1331
|
+
|
|
1332
|
+
#### `and` (логическое И)
|
|
1333
|
+
|
|
1334
|
+
Объединяет несколько условий в массив, требуя, чтобы каждое условие было
|
|
1335
|
+
выполнено.
|
|
1336
|
+
|
|
1337
|
+
```javascript
|
|
1338
|
+
// найдет документы, где surname равен 'Smith' И age равен 21
|
|
1339
|
+
const res = await rep.find({
|
|
1340
|
+
where: {
|
|
1341
|
+
and: [
|
|
1342
|
+
{surname: 'Smith'},
|
|
1343
|
+
{age: 21}
|
|
1344
|
+
],
|
|
1345
|
+
},
|
|
1346
|
+
});
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
#### `or` (логическое ИЛИ)
|
|
1350
|
+
|
|
1351
|
+
Объединяет несколько условий в массив, требуя, чтобы хотя бы одно из них было
|
|
1352
|
+
выполнено.
|
|
1353
|
+
|
|
1354
|
+
```javascript
|
|
1355
|
+
// найдет документы, где name равен 'James' ИЛИ age больше 30
|
|
1356
|
+
const res = await rep.find({
|
|
1357
|
+
where: {
|
|
1358
|
+
or: [
|
|
1359
|
+
{name: 'James'},
|
|
1360
|
+
{age: {gt: 30}}
|
|
1361
|
+
],
|
|
1362
|
+
},
|
|
1363
|
+
});
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
#### Операторы сопоставления с шаблоном
|
|
1367
|
+
|
|
1368
|
+
Операторы `like`, `nlike`, `ilike`, `nilike` предназначены для фильтрации
|
|
1369
|
+
строковых свойств на основе сопоставления с шаблоном, подобно оператору
|
|
1370
|
+
`LIKE` в SQL. Они позволяют находить значения, которые соответствуют
|
|
1371
|
+
определённой структуре, используя специальные символы.
|
|
1372
|
+
|
|
1373
|
+
**`%`** соответствует любой последовательности из нуля или более символов:
|
|
1374
|
+
|
|
1375
|
+
- `'А%'` найдет все строки, начинающиеся на "А";
|
|
1376
|
+
- `'%а'` найдет все строки, заканчивающиеся на "а";
|
|
1377
|
+
- `'%слово%'` найдет все строки, содержащие "слово" в любом месте;
|
|
1378
|
+
|
|
1379
|
+
**`_`** соответствует ровно одному любому символу:
|
|
1380
|
+
|
|
1381
|
+
- `'к_т'` найдет "кот", "кит", но не "крот" или "кт";
|
|
1382
|
+
- `'кот_'` найдет "коты", "коту" и "кота", но не "кот" или "котов";
|
|
1383
|
+
|
|
1384
|
+
Если нужно найти сами символы `%` или `_` как часть строки, их необходимо
|
|
1385
|
+
экранировать с помощью обратного слэша `\`:
|
|
1386
|
+
|
|
1387
|
+
- `'100\%'` найдет строку "100%";
|
|
1388
|
+
- `'file\_name'` найдет строку "file_name";
|
|
1389
|
+
- `'path\\to'` найдет строку "path\to";
|
|
1390
|
+
|
|
1162
1391
|
### order
|
|
1163
1392
|
|
|
1164
1393
|
Параметр упорядочивает выборку по указанным свойствам модели. Обратное
|