mongodb-adapter.spec.js 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532
  1. import net from 'net';
  2. import chai from 'chai';
  3. import {expect} from 'chai';
  4. import {ObjectId} from 'mongodb';
  5. import {MongoClient} from 'mongodb';
  6. import {format} from '@e22m4u/js-format';
  7. import {Service} from '@e22m4u/js-service';
  8. import {Schema} from '@e22m4u/js-repository';
  9. import {DataType} from '@e22m4u/js-repository';
  10. import {createMongodbUrl} from './utils/index.js';
  11. import {MongodbAdapter} from './mongodb-adapter.js';
  12. import {AdapterRegistry} from '@e22m4u/js-repository';
  13. import {DEFAULT_PRIMARY_KEY_PROPERTY_NAME as DEF_PK} from '@e22m4u/js-repository';
  14. const sandbox = chai.spy.sandbox();
  15. const CONFIG = {
  16. host: process.env.MONGODB_HOST || 'localhost',
  17. port: process.env.MONGODB_PORT || 27017,
  18. database: process.env.MONGODB_DATABASE,
  19. };
  20. const MDB_CLIENT = new MongoClient(createMongodbUrl(CONFIG));
  21. const ADAPTERS_STACK = [];
  22. function createSchema() {
  23. const schema = new Schema();
  24. const adapter = new MongodbAdapter(schema.container, CONFIG);
  25. ADAPTERS_STACK.push(adapter);
  26. schema.defineDatasource({name: 'mongodb', adapter: 'mongodb'});
  27. schema.getService(AdapterRegistry)._adapters['mongodb'] = adapter;
  28. return schema;
  29. }
  30. describe('MongodbAdapter', function () {
  31. this.timeout(15000);
  32. afterEach(async function () {
  33. sandbox.restore();
  34. await MDB_CLIENT.db(CONFIG.database).dropDatabase();
  35. });
  36. after(async function () {
  37. for await (const adapter of ADAPTERS_STACK) {
  38. await adapter.disconnect();
  39. }
  40. await MDB_CLIENT.close(true);
  41. });
  42. it('updates "connected" and "connecting" properties', async function () {
  43. const S = new Service();
  44. const events = [];
  45. const adapter = new MongodbAdapter(S.container, CONFIG);
  46. adapter.emitter.addListener('*', name => events.push(name));
  47. expect(adapter.connected).to.be.false;
  48. expect(adapter.connecting).to.be.false;
  49. expect(events).to.be.empty;
  50. const promise = adapter.connect();
  51. expect(adapter.connected).to.be.false;
  52. expect(adapter.connecting).to.be.true;
  53. expect(events).to.include('serverOpening');
  54. expect(events).to.not.include('connectionPoolReady');
  55. expect(events).to.not.include('serverClosed');
  56. await promise;
  57. expect(adapter.connected).to.be.true;
  58. expect(adapter.connecting).to.be.false;
  59. expect(events).to.include('connectionPoolReady');
  60. expect(events).to.not.include('serverClosed');
  61. await adapter.disconnect();
  62. expect(adapter.connected).to.be.false;
  63. expect(adapter.connecting).to.be.false;
  64. expect(events).to.include('serverClosed');
  65. });
  66. it('emits "connecting", "connected" and "disconnected" events', async function () {
  67. const S = new Service();
  68. const events = [];
  69. const adapter = new MongodbAdapter(S.container, CONFIG);
  70. adapter.emitter.addListener('*', name => events.push(name));
  71. expect(adapter.connected).to.be.false;
  72. expect(adapter.connecting).to.be.false;
  73. expect(events).to.be.empty;
  74. const promise = adapter.connect();
  75. expect(adapter.connected).to.be.false;
  76. expect(adapter.connecting).to.be.true;
  77. expect(events).to.include('connecting');
  78. expect(events).to.not.include('connected');
  79. expect(events).to.not.include('disconnected');
  80. await promise;
  81. expect(adapter.connected).to.be.true;
  82. expect(adapter.connecting).to.be.false;
  83. expect(events).to.include('connected');
  84. expect(events).to.not.include('disconnected');
  85. await adapter.disconnect();
  86. expect(adapter.connected).to.be.false;
  87. expect(adapter.connecting).to.be.false;
  88. expect(events).to.include('disconnected');
  89. });
  90. it('reconnects on server selection error', function (done) {
  91. const S = new Service();
  92. const server = net.createServer();
  93. let startupCounter = 0;
  94. server.listen(0, 'localhost', 2, () => {
  95. startupCounter++;
  96. expect(startupCounter).to.be.eq(1);
  97. const {address, port} = server.address();
  98. const attemptsLimit = 3;
  99. const serverSelectionTimeoutMS = 50;
  100. const adapter = new MongodbAdapter(S.container, {
  101. port,
  102. host: address,
  103. reconnectInterval: 0,
  104. serverSelectionTimeoutMS,
  105. });
  106. let attempts = 0;
  107. const startTime = new Date();
  108. adapter.emitter.addListener('connecting', () => {
  109. ++attempts;
  110. if (attempts !== attemptsLimit) return;
  111. const duration = new Date() - startTime;
  112. const accuracy = 10;
  113. server.close();
  114. adapter.disconnect();
  115. expect(adapter.connect).to.have.been.called.once;
  116. const attemptMs = duration / (attemptsLimit - 1);
  117. expect(attemptMs).to.be.gte(serverSelectionTimeoutMS - accuracy);
  118. expect(attemptMs).to.be.lte(serverSelectionTimeoutMS + accuracy);
  119. done();
  120. });
  121. adapter.emitter.addListener('error', error => {
  122. expect(error.message).to.be.eq(
  123. 'Server selection timed out after 50 ms',
  124. );
  125. });
  126. sandbox.on(adapter, 'connect');
  127. adapter.connect();
  128. });
  129. });
  130. it('reconnects on implicit disconnect', function (done) {
  131. const S = new Service();
  132. const reconnectsLimit = 2;
  133. const reconnectInterval = 50;
  134. const adapter = new MongodbAdapter(S.container, {
  135. ...CONFIG,
  136. reconnectInterval,
  137. });
  138. let startTime;
  139. let connects = 0;
  140. let reconnects = 0;
  141. adapter.emitter.on('connected', () => {
  142. ++connects;
  143. if (connects === 1) {
  144. adapter._client.close();
  145. return;
  146. }
  147. ++reconnects;
  148. if (startTime == null) startTime = new Date();
  149. if (reconnects < reconnectsLimit) {
  150. adapter._client.close();
  151. return;
  152. }
  153. const duration = new Date() - startTime;
  154. const accuracy = 10;
  155. adapter.disconnect();
  156. expect(adapter.connect).to.have.been.called.once;
  157. const attemptMs = duration / (reconnectsLimit - 1);
  158. expect(attemptMs).to.be.gt(reconnectInterval - accuracy);
  159. expect(attemptMs).to.be.lt(reconnectInterval + accuracy);
  160. expect(connects).to.be.eq(reconnectsLimit + 1);
  161. done();
  162. });
  163. sandbox.on(adapter, 'connect');
  164. adapter.connect();
  165. });
  166. it('does not reconnect on explicit disconnect', function (done) {
  167. const S = new Service();
  168. const reconnectInterval = 0;
  169. const adapter = new MongodbAdapter(S.container, {
  170. ...CONFIG,
  171. reconnectInterval,
  172. });
  173. adapter.emitter.once('connected', () => {
  174. adapter.emitter.once('connecting', () => {
  175. throw new Error('Unexpected reconnection');
  176. });
  177. adapter.emitter.once('disconnected', () => setTimeout(() => done(), 50));
  178. adapter.disconnect();
  179. });
  180. adapter.connect();
  181. });
  182. describe('create', function () {
  183. it('generates a new identifier when a value of a primary key is not provided', async function () {
  184. const schema = createSchema();
  185. schema.defineModel({name: 'model', datasource: 'mongodb'});
  186. const rep = schema.getRepository('model');
  187. const result = await rep.create({foo: 'bar'});
  188. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
  189. expect(typeof result[DEF_PK]).to.be.eq('string');
  190. expect(result[DEF_PK]).to.have.lengthOf(24);
  191. });
  192. it('generates a new identifier when a value of a primary key is undefined', async function () {
  193. const schema = createSchema();
  194. schema.defineModel({name: 'model', datasource: 'mongodb'});
  195. const rep = schema.getRepository('model');
  196. const result = await rep.create({[DEF_PK]: undefined, foo: 'bar'});
  197. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
  198. expect(typeof result[DEF_PK]).to.be.eq('string');
  199. expect(result[DEF_PK]).to.have.lengthOf(24);
  200. });
  201. it('generates a new identifier when a value of a primary key is null', async function () {
  202. const schema = createSchema();
  203. schema.defineModel({name: 'model', datasource: 'mongodb'});
  204. const rep = schema.getRepository('model');
  205. const result = await rep.create({[DEF_PK]: null, foo: 'bar'});
  206. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
  207. expect(typeof result[DEF_PK]).to.be.eq('string');
  208. expect(result[DEF_PK]).to.have.lengthOf(24);
  209. });
  210. it('generates a new identifier for a primary key of a "string" type', async function () {
  211. const schema = createSchema();
  212. schema.defineModel({
  213. name: 'model',
  214. datasource: 'mongodb',
  215. properties: {
  216. id: {
  217. type: DataType.STRING,
  218. primaryKey: true,
  219. },
  220. },
  221. });
  222. const rep = schema.getRepository('model');
  223. const result = await rep.create({[DEF_PK]: null, foo: 'bar'});
  224. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
  225. expect(typeof result[DEF_PK]).to.be.eq('string');
  226. expect(result[DEF_PK]).to.have.lengthOf(24);
  227. });
  228. it('generates a new identifier for a primary key of a "any" type', async function () {
  229. const schema = createSchema();
  230. schema.defineModel({
  231. name: 'model',
  232. datasource: 'mongodb',
  233. properties: {
  234. id: {
  235. type: DataType.ANY,
  236. primaryKey: true,
  237. },
  238. },
  239. });
  240. const rep = schema.getRepository('model');
  241. const result = await rep.create({[DEF_PK]: null, foo: 'bar'});
  242. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'bar'});
  243. expect(typeof result[DEF_PK]).to.be.eq('string');
  244. expect(result[DEF_PK]).to.have.lengthOf(24);
  245. });
  246. it('throws an error when generating a new value for a primary key of a "number" type', async function () {
  247. const schema = createSchema();
  248. schema.defineModel({
  249. name: 'model',
  250. datasource: 'mongodb',
  251. properties: {
  252. id: {
  253. type: DataType.NUMBER,
  254. primaryKey: true,
  255. },
  256. },
  257. });
  258. const rep = schema.getRepository('model');
  259. const promise = rep.create({});
  260. expect(promise).to.be.rejectedWith(
  261. 'MongoDB unable to generate primary keys of Number. ' +
  262. 'Do provide your own value for the "id" property ' +
  263. 'or set the property type to String.',
  264. );
  265. });
  266. it('throws an error when generating a new value for a primary key of a "boolean" type', async function () {
  267. const schema = createSchema();
  268. schema.defineModel({
  269. name: 'model',
  270. datasource: 'mongodb',
  271. properties: {
  272. id: {
  273. type: DataType.BOOLEAN,
  274. primaryKey: true,
  275. },
  276. },
  277. });
  278. const rep = schema.getRepository('model');
  279. const promise = rep.create({});
  280. expect(promise).to.be.rejectedWith(
  281. 'MongoDB unable to generate primary keys of Boolean. ' +
  282. 'Do provide your own value for the "id" property ' +
  283. 'or set the property type to String.',
  284. );
  285. });
  286. it('throws an error when generating a new value for a primary key of a "array" type', async function () {
  287. const schema = createSchema();
  288. schema.defineModel({
  289. name: 'model',
  290. datasource: 'mongodb',
  291. properties: {
  292. id: {
  293. type: DataType.ARRAY,
  294. primaryKey: true,
  295. },
  296. },
  297. });
  298. const rep = schema.getRepository('model');
  299. const promise = rep.create({});
  300. expect(promise).to.be.rejectedWith(
  301. 'MongoDB unable to generate primary keys of Array. ' +
  302. 'Do provide your own value for the "id" property ' +
  303. 'or set the property type to String.',
  304. );
  305. });
  306. it('throws an error when generating a new value for a primary key of a "object" type', async function () {
  307. const schema = createSchema();
  308. schema.defineModel({
  309. name: 'model',
  310. datasource: 'mongodb',
  311. properties: {
  312. id: {
  313. type: DataType.OBJECT,
  314. primaryKey: true,
  315. },
  316. },
  317. });
  318. const rep = schema.getRepository('model');
  319. const promise = rep.create({});
  320. expect(promise).to.be.rejectedWith(
  321. 'MongoDB unable to generate primary keys of Object. ' +
  322. 'Do provide your own value for the "id" property ' +
  323. 'or set the property type to String.',
  324. );
  325. });
  326. it('allows to specify an ObjectID instance for a default primary key', async function () {
  327. const schema = createSchema();
  328. schema.defineModel({name: 'model', datasource: 'mongodb'});
  329. const rep = schema.getRepository('model');
  330. const oid = new ObjectId();
  331. const result = await rep.create({[DEF_PK]: oid});
  332. expect(result).to.be.eql({[DEF_PK]: String(oid)});
  333. const rawData = await MDB_CLIENT.db()
  334. .collection('model')
  335. .findOne({_id: oid});
  336. expect(rawData).to.be.not.null;
  337. });
  338. it('allows to specify an ObjectID string for a default primary key', async function () {
  339. const schema = createSchema();
  340. schema.defineModel({name: 'model', datasource: 'mongodb'});
  341. const rep = schema.getRepository('model');
  342. const oid = new ObjectId();
  343. const id = String(oid);
  344. const result = await rep.create({[DEF_PK]: id});
  345. expect(result).to.be.eql({[DEF_PK]: id});
  346. const rawData = await MDB_CLIENT.db()
  347. .collection('model')
  348. .findOne({_id: oid});
  349. expect(rawData).to.be.not.null;
  350. });
  351. it('allows to specify an ObjectID instance for "id" primary key', async function () {
  352. const schema = createSchema();
  353. schema.defineModel({
  354. name: 'model',
  355. datasource: 'mongodb',
  356. properties: {
  357. id: {
  358. type: DataType.ANY,
  359. primaryKey: true,
  360. },
  361. },
  362. });
  363. const rep = schema.getRepository('model');
  364. const oid = new ObjectId();
  365. const result = await rep.create({id: oid});
  366. expect(result).to.be.eql({id: String(oid)});
  367. const rawData = await MDB_CLIENT.db()
  368. .collection('model')
  369. .findOne({_id: oid});
  370. expect(rawData).to.be.not.null;
  371. });
  372. it('allows to specify an ObjectID string for "id" primary key', async function () {
  373. const schema = createSchema();
  374. schema.defineModel({
  375. name: 'model',
  376. datasource: 'mongodb',
  377. properties: {
  378. id: {
  379. type: DataType.STRING,
  380. primaryKey: true,
  381. },
  382. },
  383. });
  384. const rep = schema.getRepository('model');
  385. const oid = new ObjectId();
  386. const id = String(oid);
  387. const result = await rep.create({id});
  388. expect(result).to.be.eql({id});
  389. const rawData = await MDB_CLIENT.db()
  390. .collection('model')
  391. .findOne({_id: oid});
  392. expect(rawData).to.be.not.null;
  393. });
  394. it('allows to specify an ObjectID instance for "_id" primary key', async function () {
  395. const schema = createSchema();
  396. schema.defineModel({
  397. name: 'model',
  398. datasource: 'mongodb',
  399. properties: {
  400. _id: {
  401. type: DataType.ANY,
  402. primaryKey: true,
  403. },
  404. },
  405. });
  406. const rep = schema.getRepository('model');
  407. const oid = new ObjectId();
  408. const result = await rep.create({_id: oid});
  409. expect(result).to.be.eql({_id: String(oid)});
  410. const rawData = await MDB_CLIENT.db()
  411. .collection('model')
  412. .findOne({_id: oid});
  413. expect(rawData).to.be.not.null;
  414. });
  415. it('allows to specify an ObjectID string for "_id" primary key', async function () {
  416. const schema = createSchema();
  417. schema.defineModel({
  418. name: 'model',
  419. datasource: 'mongodb',
  420. properties: {
  421. _id: {
  422. type: DataType.STRING,
  423. primaryKey: true,
  424. },
  425. },
  426. });
  427. const rep = schema.getRepository('model');
  428. const oid = new ObjectId();
  429. const id = String(oid);
  430. const result = await rep.create({_id: id});
  431. expect(result).to.be.eql({_id: id});
  432. const rawData = await MDB_CLIENT.db()
  433. .collection('model')
  434. .findOne({_id: oid});
  435. expect(rawData).to.be.not.null;
  436. });
  437. it('throws an error for a custom primary key', async function () {
  438. const schema = createSchema();
  439. schema.defineModel({
  440. name: 'model',
  441. datasource: 'mongodb',
  442. properties: {
  443. myId: {
  444. type: DataType.ANY,
  445. primaryKey: true,
  446. },
  447. },
  448. });
  449. const rep = schema.getRepository('model');
  450. const oid = new ObjectId();
  451. const promise = rep.create({myId: oid});
  452. await expect(promise).to.be.rejectedWith(
  453. 'MongoDB is not supporting custom names of the primary key. ' +
  454. 'Do use "id" as a primary key instead of "myId".',
  455. );
  456. });
  457. it('throws an error if a given "number" identifier already exists', async function () {
  458. const schema = createSchema();
  459. schema.defineModel({name: 'model', datasource: 'mongodb'});
  460. const rep = schema.getRepository('model');
  461. await rep.create({[DEF_PK]: 10});
  462. const promise = rep.create({[DEF_PK]: 10});
  463. await expect(promise).to.be.rejectedWith(
  464. 'E11000 duplicate key error collection: test.model index: ' +
  465. '_id_ dup key: { _id: 10 }',
  466. );
  467. });
  468. it('throws an error if a given "string" identifier already exists', async function () {
  469. const schema = createSchema();
  470. schema.defineModel({name: 'model', datasource: 'mongodb'});
  471. const rep = schema.getRepository('model');
  472. await rep.create({[DEF_PK]: 'str'});
  473. const promise = rep.create({[DEF_PK]: 'str'});
  474. await expect(promise).to.be.rejectedWith(
  475. 'E11000 duplicate key error collection: test.model index: ' +
  476. '_id_ dup key: { _id: "str" }',
  477. );
  478. });
  479. it('throws an error if a given ObjectId instance identifier already exists', async function () {
  480. const schema = createSchema();
  481. schema.defineModel({name: 'model', datasource: 'mongodb'});
  482. const rep = schema.getRepository('model');
  483. const oid = new ObjectId();
  484. await rep.create({[DEF_PK]: oid});
  485. const promise = rep.create({[DEF_PK]: oid});
  486. await expect(promise).to.be.rejectedWith(
  487. format(
  488. 'E11000 duplicate key error collection: test.model index: ' +
  489. "_id_ dup key: { _id: ObjectId('%s') }",
  490. oid,
  491. ),
  492. );
  493. });
  494. it('throws an error if a given ObjectId string identifier already exists', async function () {
  495. const schema = createSchema();
  496. schema.defineModel({name: 'model', datasource: 'mongodb'});
  497. const rep = schema.getRepository('model');
  498. const oid = new ObjectId();
  499. const id = String(oid);
  500. await rep.create({[DEF_PK]: id});
  501. const promise = rep.create({[DEF_PK]: id});
  502. await expect(promise).to.be.rejectedWith(
  503. format(
  504. 'E11000 duplicate key error collection: test.model index: ' +
  505. "_id_ dup key: { _id: ObjectId('%s') }",
  506. id,
  507. ),
  508. );
  509. });
  510. it('uses a specified column name for a regular property', async function () {
  511. const schema = createSchema();
  512. schema.defineModel({
  513. name: 'model',
  514. datasource: 'mongodb',
  515. properties: {
  516. foo: {
  517. type: DataType.NUMBER,
  518. columnName: 'bar',
  519. },
  520. },
  521. });
  522. const rep = schema.getRepository('model');
  523. const result = await rep.create({foo: 10});
  524. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
  525. const oid = new ObjectId(result[DEF_PK]);
  526. const rawData = await MDB_CLIENT.db()
  527. .collection('model')
  528. .findOne({_id: oid});
  529. expect(rawData).to.be.eql({_id: oid, bar: 10});
  530. });
  531. it('uses a specified column name for a regular property with a default value', async function () {
  532. const schema = createSchema();
  533. schema.defineModel({
  534. name: 'model',
  535. datasource: 'mongodb',
  536. properties: {
  537. foo: {
  538. type: DataType.NUMBER,
  539. columnName: 'bar',
  540. default: 10,
  541. },
  542. },
  543. });
  544. const rep = schema.getRepository('model');
  545. const result = await rep.create({});
  546. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
  547. const oid = new ObjectId(result[DEF_PK]);
  548. const rawData = await MDB_CLIENT.db()
  549. .collection('model')
  550. .findOne({_id: oid});
  551. expect(rawData).to.be.eql({_id: oid, bar: 10});
  552. });
  553. it('stores a Date instance as date and returns string type', async function () {
  554. const schema = createSchema();
  555. schema.defineModel({name: 'model', datasource: 'mongodb'});
  556. const rep = schema.getRepository('model');
  557. const date = new Date();
  558. const dateString = date.toISOString();
  559. const result = await rep.create({date});
  560. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], date: dateString});
  561. const oid = new ObjectId(result[DEF_PK]);
  562. const rawData = await MDB_CLIENT.db()
  563. .collection('model')
  564. .findOne({_id: oid});
  565. expect(rawData).to.be.eql({_id: oid, date});
  566. });
  567. it('stores a Date string as date and returns string type', async function () {
  568. const schema = createSchema();
  569. schema.defineModel({name: 'model', datasource: 'mongodb'});
  570. const rep = schema.getRepository('model');
  571. const date = new Date();
  572. const dateString = date.toISOString();
  573. const result = await rep.create({date: dateString});
  574. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], date: dateString});
  575. const oid = new ObjectId(result[DEF_PK]);
  576. const rawData = await MDB_CLIENT.db()
  577. .collection('model')
  578. .findOne({_id: oid});
  579. expect(rawData).to.be.eql({_id: oid, date});
  580. });
  581. it('stores a string as is', async function () {
  582. const schema = createSchema();
  583. schema.defineModel({name: 'model', datasource: 'mongodb'});
  584. const rep = schema.getRepository('model');
  585. const result = await rep.create({foo: 'str'});
  586. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 'str'});
  587. const oid = new ObjectId(result[DEF_PK]);
  588. const rawData = await MDB_CLIENT.db()
  589. .collection('model')
  590. .findOne({_id: oid});
  591. expect(rawData).to.be.eql({_id: oid, foo: 'str'});
  592. });
  593. it('stores a number as is', async function () {
  594. const schema = createSchema();
  595. schema.defineModel({name: 'model', datasource: 'mongodb'});
  596. const rep = schema.getRepository('model');
  597. const result = await rep.create({foo: 10});
  598. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
  599. const oid = new ObjectId(result[DEF_PK]);
  600. const rawData = await MDB_CLIENT.db()
  601. .collection('model')
  602. .findOne({_id: oid});
  603. expect(rawData).to.be.eql({_id: oid, foo: 10});
  604. });
  605. it('stores a boolean as is', async function () {
  606. const schema = createSchema();
  607. schema.defineModel({name: 'model', datasource: 'mongodb'});
  608. const rep = schema.getRepository('model');
  609. const result = await rep.create({foo: true, bar: false});
  610. expect(result).to.be.eql({
  611. [DEF_PK]: result[DEF_PK],
  612. foo: true,
  613. bar: false,
  614. });
  615. const oid = new ObjectId(result[DEF_PK]);
  616. const rawData = await MDB_CLIENT.db()
  617. .collection('model')
  618. .findOne({_id: oid});
  619. expect(rawData).to.be.eql({_id: oid, foo: true, bar: false});
  620. });
  621. it('stores an array as is', async function () {
  622. const schema = createSchema();
  623. schema.defineModel({name: 'model', datasource: 'mongodb'});
  624. const rep = schema.getRepository('model');
  625. const result = await rep.create({foo: ['bar']});
  626. expect(result).to.be.eql({
  627. [DEF_PK]: result[DEF_PK],
  628. foo: ['bar'],
  629. });
  630. const oid = new ObjectId(result[DEF_PK]);
  631. const rawData = await MDB_CLIENT.db()
  632. .collection('model')
  633. .findOne({_id: oid});
  634. expect(rawData).to.be.eql({_id: oid, foo: ['bar']});
  635. });
  636. it('stores an object as is', async function () {
  637. const schema = createSchema();
  638. schema.defineModel({name: 'model', datasource: 'mongodb'});
  639. const rep = schema.getRepository('model');
  640. const result = await rep.create({foo: {bar: 10}});
  641. expect(result).to.be.eql({
  642. [DEF_PK]: result[DEF_PK],
  643. foo: {bar: 10},
  644. });
  645. const oid = new ObjectId(result[DEF_PK]);
  646. const rawData = await MDB_CLIENT.db()
  647. .collection('model')
  648. .findOne({_id: oid});
  649. expect(rawData).to.be.eql({_id: oid, foo: {bar: 10}});
  650. });
  651. it('stores an undefined as null', async function () {
  652. const schema = createSchema();
  653. schema.defineModel({name: 'model', datasource: 'mongodb'});
  654. const rep = schema.getRepository('model');
  655. const result = await rep.create({foo: undefined});
  656. expect(result).to.be.eql({
  657. [DEF_PK]: result[DEF_PK],
  658. foo: null,
  659. });
  660. const oid = new ObjectId(result[DEF_PK]);
  661. const rawData = await MDB_CLIENT.db()
  662. .collection('model')
  663. .findOne({_id: oid});
  664. expect(rawData).to.be.eql({_id: oid, foo: null});
  665. });
  666. it('stores an null as is', async function () {
  667. const schema = createSchema();
  668. schema.defineModel({name: 'model', datasource: 'mongodb'});
  669. const rep = schema.getRepository('model');
  670. const result = await rep.create({foo: null});
  671. expect(result).to.be.eql({
  672. [DEF_PK]: result[DEF_PK],
  673. foo: null,
  674. });
  675. const oid = new ObjectId(result[DEF_PK]);
  676. const rawData = await MDB_CLIENT.db()
  677. .collection('model')
  678. .findOne({_id: oid});
  679. expect(rawData).to.be.eql({_id: oid, foo: null});
  680. });
  681. it('uses a short fields clause to filter results', async function () {
  682. const schema = createSchema();
  683. schema.defineModel({name: 'model', datasource: 'mongodb'});
  684. const rep = schema.getRepository('model');
  685. const result = await rep.create({foo: 10, bar: 20}, {fields: 'foo'});
  686. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10});
  687. });
  688. it('uses a full fields clause to filter results', async function () {
  689. const schema = createSchema();
  690. schema.defineModel({name: 'model', datasource: 'mongodb'});
  691. const rep = schema.getRepository('model');
  692. const result = await rep.create(
  693. {foo: 10, bar: 20, baz: 30},
  694. {fields: ['foo', 'bar']},
  695. );
  696. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK], foo: 10, bar: 20});
  697. const oid = new ObjectId(result[DEF_PK]);
  698. const rawData = await MDB_CLIENT.db()
  699. .collection('model')
  700. .findOne({_id: oid});
  701. expect(rawData).to.be.eql({_id: oid, foo: 10, bar: 20, baz: 30});
  702. });
  703. it('a fields clause uses property names instead of column names', async function () {
  704. const schema = createSchema();
  705. schema.defineModel({
  706. name: 'model',
  707. datasource: 'mongodb',
  708. properties: {
  709. foo: {
  710. type: DataType.NUMBER,
  711. columnName: 'fooCol',
  712. },
  713. bar: {
  714. type: DataType.NUMBER,
  715. columnName: 'barCol',
  716. },
  717. baz: {
  718. type: DataType.NUMBER,
  719. columnName: 'bazCol',
  720. },
  721. },
  722. });
  723. const rep = schema.getRepository('model');
  724. const result = await rep.create(
  725. {foo: 10, bar: 20, baz: 30},
  726. {fields: ['fooCol', 'barCol']},
  727. );
  728. expect(result).to.be.eql({[DEF_PK]: result[DEF_PK]});
  729. });
  730. });
  731. describe('replaceById', function () {
  732. it('removes properties when replacing an item by a given identifier', async function () {
  733. const schema = createSchema();
  734. schema.defineModel({name: 'model', datasource: 'mongodb'});
  735. const rep = schema.getRepository('model');
  736. const created = await rep.create({foo: 10});
  737. const id = created[DEF_PK];
  738. const replaced = await rep.replaceById(id, {bar: 20});
  739. expect(replaced).to.be.eql({[DEF_PK]: id, bar: 20});
  740. const oid = new ObjectId(id);
  741. const rawData = await MDB_CLIENT.db()
  742. .collection('model')
  743. .findOne({_id: oid});
  744. expect(rawData).to.be.eql({_id: oid, bar: 20});
  745. });
  746. it('ignores identifier value in a given data in case of a default primary key', async function () {
  747. const schema = createSchema();
  748. schema.defineModel({name: 'model', datasource: 'mongodb'});
  749. const rep = schema.getRepository('model');
  750. await rep.create({[DEF_PK]: 'foo', prop: 10});
  751. const replaced = await rep.replaceById('foo', {
  752. [DEF_PK]: 'bar',
  753. prop: 20,
  754. });
  755. expect(replaced).to.be.eql({[DEF_PK]: 'foo', prop: 20});
  756. const rawData = await MDB_CLIENT.db()
  757. .collection('model')
  758. .findOne({_id: 'foo'});
  759. expect(rawData).to.be.eql({_id: 'foo', prop: 20});
  760. });
  761. it('ignores identifier value in a given data in case of a custom primary key', async function () {
  762. const schema = createSchema();
  763. schema.defineModel({
  764. name: 'model',
  765. datasource: 'mongodb',
  766. properties: {
  767. myId: {
  768. type: DataType.STRING,
  769. primaryKey: true,
  770. columnName: '_id',
  771. },
  772. },
  773. });
  774. const rep = schema.getRepository('model');
  775. await rep.create({myId: 'foo', prop: 10});
  776. const replaced = await rep.replaceById('foo', {myId: 'bar', prop: 20});
  777. expect(replaced).to.be.eql({myId: 'foo', prop: 20});
  778. const rawData = await MDB_CLIENT.db()
  779. .collection('model')
  780. .findOne({_id: 'foo'});
  781. expect(rawData).to.be.eql({_id: 'foo', prop: 20});
  782. });
  783. it('throws an error if a given identifier does not exist', async function () {
  784. const schema = createSchema();
  785. schema.defineModel({name: 'model', datasource: 'mongodb'});
  786. const rep = schema.getRepository('model');
  787. const oid = new ObjectId();
  788. const promise = rep.replaceById(oid, {foo: 10});
  789. await expect(promise).to.be.rejectedWith(
  790. format('Identifier "%s" is not found.', oid),
  791. );
  792. });
  793. it('throws an error for a custom primary key', async function () {
  794. const schema = createSchema();
  795. schema.defineModel({
  796. name: 'model',
  797. datasource: 'mongodb',
  798. properties: {
  799. myId: {
  800. type: DataType.ANY,
  801. primaryKey: true,
  802. },
  803. },
  804. });
  805. const rep = schema.getRepository('model');
  806. const promise = rep.replaceById('id', {foo: 10});
  807. await expect(promise).to.be.rejectedWith(
  808. 'MongoDB is not supporting custom names of the primary key. ' +
  809. 'Do use "id" as a primary key instead of "myId".',
  810. );
  811. });
  812. it('uses a specified column name for a regular property', async function () {
  813. const schema = createSchema();
  814. schema.defineModel({
  815. name: 'model',
  816. datasource: 'mongodb',
  817. properties: {
  818. foo: {
  819. type: DataType.NUMBER,
  820. columnName: 'bar',
  821. },
  822. },
  823. });
  824. const rep = schema.getRepository('model');
  825. const created = await rep.create({foo: 10});
  826. const id = created[DEF_PK];
  827. const replaced = await rep.replaceById(id, {foo: 20});
  828. expect(replaced).to.be.eql({[DEF_PK]: id, foo: 20});
  829. const oid = new ObjectId(id);
  830. const rawData = await MDB_CLIENT.db()
  831. .collection('model')
  832. .findOne({_id: oid});
  833. expect(rawData).to.be.eql({_id: oid, bar: 20});
  834. });
  835. it('stores a Date instance as date and returns string type', async function () {
  836. const schema = createSchema();
  837. schema.defineModel({name: 'model', datasource: 'mongodb'});
  838. const rep = schema.getRepository('model');
  839. const date = new Date();
  840. const dateString = date.toISOString();
  841. const created = await rep.create({date: null});
  842. const id = created[DEF_PK];
  843. const replaced = await rep.replaceById(id, {date});
  844. expect(replaced).to.be.eql({[DEF_PK]: id, date: dateString});
  845. const oid = new ObjectId(id);
  846. const rawData = await MDB_CLIENT.db()
  847. .collection('model')
  848. .findOne({_id: oid});
  849. expect(rawData).to.be.eql({_id: oid, date});
  850. });
  851. it('stores a Date string as date and returns string type', async function () {
  852. const schema = createSchema();
  853. schema.defineModel({name: 'model', datasource: 'mongodb'});
  854. const rep = schema.getRepository('model');
  855. const date = new Date();
  856. const dateString = date.toISOString();
  857. const created = await rep.create({date: null});
  858. const id = created[DEF_PK];
  859. const replaced = await rep.replaceById(id, {date: dateString});
  860. expect(replaced).to.be.eql({[DEF_PK]: id, date: dateString});
  861. const oid = new ObjectId(id);
  862. const rawData = await MDB_CLIENT.db()
  863. .collection('model')
  864. .findOne({_id: oid});
  865. expect(rawData).to.be.eql({_id: oid, date});
  866. });
  867. it('stores a string as is', async function () {
  868. const schema = createSchema();
  869. schema.defineModel({name: 'model', datasource: 'mongodb'});
  870. const rep = schema.getRepository('model');
  871. const created = await rep.create({foo: null});
  872. const id = created[DEF_PK];
  873. const replaced = await rep.replaceById(id, {foo: 'str'});
  874. expect(replaced).to.be.eql({[DEF_PK]: id, foo: 'str'});
  875. const oid = new ObjectId(id);
  876. const rawData = await MDB_CLIENT.db()
  877. .collection('model')
  878. .findOne({_id: oid});
  879. expect(rawData).to.be.eql({_id: oid, foo: 'str'});
  880. });
  881. it('stores a number as is', async function () {
  882. const schema = createSchema();
  883. schema.defineModel({name: 'model', datasource: 'mongodb'});
  884. const rep = schema.getRepository('model');
  885. const created = await rep.create({foo: null});
  886. const id = created[DEF_PK];
  887. const replaced = await rep.replaceById(id, {foo: 10});
  888. expect(replaced).to.be.eql({[DEF_PK]: id, foo: 10});
  889. const oid = new ObjectId(id);
  890. const rawData = await MDB_CLIENT.db()
  891. .collection('model')
  892. .findOne({_id: oid});
  893. expect(rawData).to.be.eql({_id: oid, foo: 10});
  894. });
  895. it('stores a boolean as is', async function () {
  896. const schema = createSchema();
  897. schema.defineModel({name: 'model', datasource: 'mongodb'});
  898. const rep = schema.getRepository('model');
  899. const created = await rep.create({foo: null, bar: null});
  900. const id = created[DEF_PK];
  901. const replaced = await rep.replaceById(id, {foo: true, bar: false});
  902. expect(replaced).to.be.eql({[DEF_PK]: id, foo: true, bar: false});
  903. const oid = new ObjectId(id);
  904. const rawData = await MDB_CLIENT.db()
  905. .collection('model')
  906. .findOne({_id: oid});
  907. expect(rawData).to.be.eql({_id: oid, foo: true, bar: false});
  908. });
  909. it('stores an array as is', async function () {
  910. const schema = createSchema();
  911. schema.defineModel({name: 'model', datasource: 'mongodb'});
  912. const rep = schema.getRepository('model');
  913. const created = await rep.create({foo: null});
  914. const id = created[DEF_PK];
  915. const replaced = await rep.replaceById(id, {foo: ['bar']});
  916. expect(replaced).to.be.eql({[DEF_PK]: id, foo: ['bar']});
  917. const oid = new ObjectId(id);
  918. const rawData = await MDB_CLIENT.db()
  919. .collection('model')
  920. .findOne({_id: oid});
  921. expect(rawData).to.be.eql({_id: oid, foo: ['bar']});
  922. });
  923. it('stores an object as is', async function () {
  924. const schema = createSchema();
  925. schema.defineModel({name: 'model', datasource: 'mongodb'});
  926. const rep = schema.getRepository('model');
  927. const created = await rep.create({foo: null});
  928. const id = created[DEF_PK];
  929. const replaced = await rep.replaceById(id, {foo: {bar: 10}});
  930. expect(replaced).to.be.eql({[DEF_PK]: id, foo: {bar: 10}});
  931. const oid = new ObjectId(id);
  932. const rawData = await MDB_CLIENT.db()
  933. .collection('model')
  934. .findOne({_id: oid});
  935. expect(rawData).to.be.eql({_id: oid, foo: {bar: 10}});
  936. });
  937. it('stores an undefined as null', async function () {
  938. const schema = createSchema();
  939. schema.defineModel({name: 'model', datasource: 'mongodb'});
  940. const rep = schema.getRepository('model');
  941. const created = await rep.create({foo: 10});
  942. const id = created[DEF_PK];
  943. const replaced = await rep.replaceById(id, {foo: undefined});
  944. expect(replaced).to.be.eql({[DEF_PK]: id, foo: null});
  945. const oid = new ObjectId(id);
  946. const rawData = await MDB_CLIENT.db()
  947. .collection('model')
  948. .findOne({_id: oid});
  949. expect(rawData).to.be.eql({_id: oid, foo: null});
  950. });
  951. it('stores an null as is', async function () {
  952. const schema = createSchema();
  953. schema.defineModel({name: 'model', datasource: 'mongodb'});
  954. const rep = schema.getRepository('model');
  955. const created = await rep.create({foo: 10});
  956. const id = created[DEF_PK];
  957. const replaced = await rep.replaceById(id, {foo: null});
  958. expect(replaced).to.be.eql({[DEF_PK]: id, foo: null});
  959. const oid = new ObjectId(id);
  960. const rawData = await MDB_CLIENT.db()
  961. .collection('model')
  962. .findOne({_id: oid});
  963. expect(rawData).to.be.eql({_id: oid, foo: null});
  964. });
  965. it('uses a short fields clause to filter results', async function () {
  966. const schema = createSchema();
  967. schema.defineModel({name: 'model', datasource: 'mongodb'});
  968. const rep = schema.getRepository('model');
  969. const created = await rep.create({foo: 10, bar: 20});
  970. const id = created[DEF_PK];
  971. const replaced = await rep.replaceById(
  972. id,
  973. {foo: 15, bar: 25},
  974. {fields: 'foo'},
  975. );
  976. expect(replaced).to.be.eql({[DEF_PK]: id, foo: 15});
  977. const oid = new ObjectId(id);
  978. const rawData = await MDB_CLIENT.db()
  979. .collection('model')
  980. .findOne({_id: oid});
  981. expect(rawData).to.be.eql({_id: oid, foo: 15, bar: 25});
  982. });
  983. it('uses a full fields clause to filter results', async function () {
  984. const schema = createSchema();
  985. schema.defineModel({name: 'model', datasource: 'mongodb'});
  986. const rep = schema.getRepository('model');
  987. const created = await rep.create({foo: 10, bar: 20, baz: 30});
  988. const id = created[DEF_PK];
  989. const replaced = await rep.replaceById(
  990. id,
  991. {foo: 15, bar: 25, baz: 35},
  992. {fields: ['foo', 'bar']},
  993. );
  994. expect(replaced).to.be.eql({[DEF_PK]: id, foo: 15, bar: 25});
  995. const oid = new ObjectId(id);
  996. const rawData = await MDB_CLIENT.db()
  997. .collection('model')
  998. .findOne({_id: oid});
  999. expect(rawData).to.be.eql({_id: oid, foo: 15, bar: 25, baz: 35});
  1000. });
  1001. it('a fields clause uses property names instead of column names', async function () {
  1002. const schema = createSchema();
  1003. schema.defineModel({
  1004. name: 'model',
  1005. datasource: 'mongodb',
  1006. properties: {
  1007. foo: {
  1008. type: DataType.NUMBER,
  1009. columnName: 'fooCol',
  1010. },
  1011. bar: {
  1012. type: DataType.NUMBER,
  1013. columnName: 'barCol',
  1014. },
  1015. baz: {
  1016. type: DataType.NUMBER,
  1017. columnName: 'bazCol',
  1018. },
  1019. },
  1020. });
  1021. const rep = schema.getRepository('model');
  1022. const created = await rep.create(
  1023. {foo: 10, bar: 20, baz: 30},
  1024. {fields: ['fooCol', 'barCol']},
  1025. );
  1026. const id = created[DEF_PK];
  1027. const replaced = await rep.replaceById(
  1028. id,
  1029. {foo: 15, bar: 25, baz: 35},
  1030. {fields: ['fooCol', 'barCol']},
  1031. );
  1032. expect(replaced).to.be.eql({[DEF_PK]: replaced[DEF_PK]});
  1033. const oid = new ObjectId(id);
  1034. const rawData = await MDB_CLIENT.db()
  1035. .collection('model')
  1036. .findOne({_id: oid});
  1037. expect(rawData).to.be.eql({_id: oid, fooCol: 15, barCol: 25, bazCol: 35});
  1038. });
  1039. });
  1040. describe('patchById', function () {
  1041. it('updates only provided properties by a given identifier', async function () {
  1042. const schema = createSchema();
  1043. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1044. const rep = schema.getRepository('model');
  1045. const created = await rep.create({foo: 10});
  1046. const id = created[DEF_PK];
  1047. const patched = await rep.patchById(id, {bar: 20});
  1048. expect(patched).to.be.eql({[DEF_PK]: id, foo: 10, bar: 20});
  1049. const oid = new ObjectId(id);
  1050. const rawData = await MDB_CLIENT.db()
  1051. .collection('model')
  1052. .findOne({_id: oid});
  1053. expect(rawData).to.be.eql({_id: oid, foo: 10, bar: 20});
  1054. });
  1055. it('does not throw an error if a partial data does not have required property', async function () {
  1056. const schema = createSchema();
  1057. schema.defineModel({
  1058. name: 'model',
  1059. datasource: 'mongodb',
  1060. properties: {
  1061. foo: {
  1062. type: DataType.NUMBER,
  1063. required: true,
  1064. },
  1065. },
  1066. });
  1067. const rep = schema.getRepository('model');
  1068. const {insertedId: oid} = await MDB_CLIENT.db()
  1069. .collection('model')
  1070. .insertOne({bar: 10});
  1071. const patched = await rep.patchById(oid, {baz: 20});
  1072. const id = String(oid);
  1073. expect(patched).to.be.eql({[DEF_PK]: id, bar: 10, baz: 20});
  1074. const rawData = await MDB_CLIENT.db()
  1075. .collection('model')
  1076. .findOne({_id: oid});
  1077. expect(rawData).to.be.eql({_id: oid, bar: 10, baz: 20});
  1078. });
  1079. it('ignores identifier value in a given data in case of a default primary key', async function () {
  1080. const schema = createSchema();
  1081. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1082. const rep = schema.getRepository('model');
  1083. await rep.create({[DEF_PK]: 'foo', prop: 10});
  1084. const patched = await rep.patchById('foo', {
  1085. [DEF_PK]: 'bar',
  1086. prop: 20,
  1087. });
  1088. expect(patched).to.be.eql({[DEF_PK]: 'foo', prop: 20});
  1089. const rawData = await MDB_CLIENT.db()
  1090. .collection('model')
  1091. .findOne({_id: 'foo'});
  1092. expect(rawData).to.be.eql({_id: 'foo', prop: 20});
  1093. });
  1094. it('ignores identifier value in a given data in case of a custom primary key', async function () {
  1095. const schema = createSchema();
  1096. schema.defineModel({
  1097. name: 'model',
  1098. datasource: 'mongodb',
  1099. properties: {
  1100. myId: {
  1101. type: DataType.STRING,
  1102. primaryKey: true,
  1103. columnName: '_id',
  1104. },
  1105. },
  1106. });
  1107. const rep = schema.getRepository('model');
  1108. await rep.create({myId: 'foo', prop: 10});
  1109. const patched = await rep.patchById('foo', {myId: 'bar', prop: 20});
  1110. expect(patched).to.be.eql({myId: 'foo', prop: 20});
  1111. const rawData = await MDB_CLIENT.db()
  1112. .collection('model')
  1113. .findOne({_id: 'foo'});
  1114. expect(rawData).to.be.eql({_id: 'foo', prop: 20});
  1115. });
  1116. it('throws an error if a given identifier does not exist', async function () {
  1117. const schema = createSchema();
  1118. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1119. const rep = schema.getRepository('model');
  1120. const oid = new ObjectId();
  1121. const promise = rep.patchById(oid, {foo: 10});
  1122. await expect(promise).to.be.rejectedWith(
  1123. format('Identifier "%s" is not found.', oid),
  1124. );
  1125. });
  1126. it('throws an error for a custom primary key', async function () {
  1127. const schema = createSchema();
  1128. schema.defineModel({
  1129. name: 'model',
  1130. datasource: 'mongodb',
  1131. properties: {
  1132. myId: {
  1133. type: DataType.ANY,
  1134. primaryKey: true,
  1135. },
  1136. },
  1137. });
  1138. const rep = schema.getRepository('model');
  1139. const promise = rep.patchById('id', {foo: 10});
  1140. await expect(promise).to.be.rejectedWith(
  1141. 'MongoDB is not supporting custom names of the primary key. ' +
  1142. 'Do use "id" as a primary key instead of "myId".',
  1143. );
  1144. });
  1145. it('uses a specified column name for a regular property', async function () {
  1146. const schema = createSchema();
  1147. schema.defineModel({
  1148. name: 'model',
  1149. datasource: 'mongodb',
  1150. properties: {
  1151. foo: {
  1152. type: DataType.NUMBER,
  1153. columnName: 'bar',
  1154. },
  1155. },
  1156. });
  1157. const rep = schema.getRepository('model');
  1158. const created = await rep.create({foo: 10});
  1159. const id = created[DEF_PK];
  1160. const patched = await rep.replaceById(id, {foo: 20});
  1161. expect(patched).to.be.eql({[DEF_PK]: id, foo: 20});
  1162. const oid = new ObjectId(id);
  1163. const rawData = await MDB_CLIENT.db()
  1164. .collection('model')
  1165. .findOne({_id: oid});
  1166. expect(rawData).to.be.eql({_id: oid, bar: 20});
  1167. });
  1168. it('stores a Date instance as date and returns string type', async function () {
  1169. const schema = createSchema();
  1170. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1171. const rep = schema.getRepository('model');
  1172. const date = new Date();
  1173. const dateString = date.toISOString();
  1174. const created = await rep.create({date: null});
  1175. const id = created[DEF_PK];
  1176. const patched = await rep.patchById(id, {date});
  1177. expect(patched).to.be.eql({[DEF_PK]: id, date: dateString});
  1178. const oid = new ObjectId(id);
  1179. const rawData = await MDB_CLIENT.db()
  1180. .collection('model')
  1181. .findOne({_id: oid});
  1182. expect(rawData).to.be.eql({_id: oid, date});
  1183. });
  1184. it('stores a Date string as date and returns string type', async function () {
  1185. const schema = createSchema();
  1186. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1187. const rep = schema.getRepository('model');
  1188. const date = new Date();
  1189. const dateString = date.toISOString();
  1190. const created = await rep.create({date: null});
  1191. const id = created[DEF_PK];
  1192. const patched = await rep.patchById(id, {date: dateString});
  1193. expect(patched).to.be.eql({[DEF_PK]: id, date: dateString});
  1194. const oid = new ObjectId(id);
  1195. const rawData = await MDB_CLIENT.db()
  1196. .collection('model')
  1197. .findOne({_id: oid});
  1198. expect(rawData).to.be.eql({_id: oid, date});
  1199. });
  1200. it('stores a string as is', async function () {
  1201. const schema = createSchema();
  1202. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1203. const rep = schema.getRepository('model');
  1204. const created = await rep.create({foo: null});
  1205. const id = created[DEF_PK];
  1206. const patched = await rep.patchById(id, {foo: 'str'});
  1207. expect(patched).to.be.eql({[DEF_PK]: id, foo: 'str'});
  1208. const oid = new ObjectId(id);
  1209. const rawData = await MDB_CLIENT.db()
  1210. .collection('model')
  1211. .findOne({_id: oid});
  1212. expect(rawData).to.be.eql({_id: oid, foo: 'str'});
  1213. });
  1214. it('stores a number as is', async function () {
  1215. const schema = createSchema();
  1216. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1217. const rep = schema.getRepository('model');
  1218. const created = await rep.create({foo: null});
  1219. const id = created[DEF_PK];
  1220. const patched = await rep.patchById(id, {foo: 10});
  1221. expect(patched).to.be.eql({[DEF_PK]: id, foo: 10});
  1222. const oid = new ObjectId(id);
  1223. const rawData = await MDB_CLIENT.db()
  1224. .collection('model')
  1225. .findOne({_id: oid});
  1226. expect(rawData).to.be.eql({_id: oid, foo: 10});
  1227. });
  1228. it('stores a boolean as is', async function () {
  1229. const schema = createSchema();
  1230. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1231. const rep = schema.getRepository('model');
  1232. const created = await rep.create({foo: null, bar: null});
  1233. const id = created[DEF_PK];
  1234. const patched = await rep.patchById(id, {foo: true, bar: false});
  1235. expect(patched).to.be.eql({[DEF_PK]: id, foo: true, bar: false});
  1236. const oid = new ObjectId(id);
  1237. const rawData = await MDB_CLIENT.db()
  1238. .collection('model')
  1239. .findOne({_id: oid});
  1240. expect(rawData).to.be.eql({_id: oid, foo: true, bar: false});
  1241. });
  1242. it('stores an array as is', async function () {
  1243. const schema = createSchema();
  1244. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1245. const rep = schema.getRepository('model');
  1246. const created = await rep.create({foo: null});
  1247. const id = created[DEF_PK];
  1248. const patched = await rep.patchById(id, {foo: ['bar']});
  1249. expect(patched).to.be.eql({[DEF_PK]: id, foo: ['bar']});
  1250. const oid = new ObjectId(id);
  1251. const rawData = await MDB_CLIENT.db()
  1252. .collection('model')
  1253. .findOne({_id: oid});
  1254. expect(rawData).to.be.eql({_id: oid, foo: ['bar']});
  1255. });
  1256. it('stores an object as is', async function () {
  1257. const schema = createSchema();
  1258. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1259. const rep = schema.getRepository('model');
  1260. const created = await rep.create({foo: null});
  1261. const id = created[DEF_PK];
  1262. const patched = await rep.patchById(id, {foo: {bar: 10}});
  1263. expect(patched).to.be.eql({[DEF_PK]: id, foo: {bar: 10}});
  1264. const oid = new ObjectId(id);
  1265. const rawData = await MDB_CLIENT.db()
  1266. .collection('model')
  1267. .findOne({_id: oid});
  1268. expect(rawData).to.be.eql({_id: oid, foo: {bar: 10}});
  1269. });
  1270. it('stores an undefined as null', async function () {
  1271. const schema = createSchema();
  1272. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1273. const rep = schema.getRepository('model');
  1274. const created = await rep.create({foo: 10});
  1275. const id = created[DEF_PK];
  1276. const patched = await rep.patchById(id, {foo: undefined});
  1277. expect(patched).to.be.eql({[DEF_PK]: id, foo: null});
  1278. const oid = new ObjectId(id);
  1279. const rawData = await MDB_CLIENT.db()
  1280. .collection('model')
  1281. .findOne({_id: oid});
  1282. expect(rawData).to.be.eql({_id: oid, foo: null});
  1283. });
  1284. it('stores an null as is', async function () {
  1285. const schema = createSchema();
  1286. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1287. const rep = schema.getRepository('model');
  1288. const created = await rep.create({foo: 10});
  1289. const id = created[DEF_PK];
  1290. const patched = await rep.patchById(id, {foo: null});
  1291. expect(patched).to.be.eql({[DEF_PK]: id, foo: null});
  1292. const oid = new ObjectId(id);
  1293. const rawData = await MDB_CLIENT.db()
  1294. .collection('model')
  1295. .findOne({_id: oid});
  1296. expect(rawData).to.be.eql({_id: oid, foo: null});
  1297. });
  1298. it('uses a short fields clause to filter results', async function () {
  1299. const schema = createSchema();
  1300. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1301. const rep = schema.getRepository('model');
  1302. const created = await rep.create({foo: 10, bar: 20});
  1303. const id = created[DEF_PK];
  1304. const patched = await rep.patchById(
  1305. id,
  1306. {foo: 15, bar: 25},
  1307. {fields: 'foo'},
  1308. );
  1309. expect(patched).to.be.eql({[DEF_PK]: id, foo: 15});
  1310. const oid = new ObjectId(id);
  1311. const rawData = await MDB_CLIENT.db()
  1312. .collection('model')
  1313. .findOne({_id: oid});
  1314. expect(rawData).to.be.eql({_id: oid, foo: 15, bar: 25});
  1315. });
  1316. it('uses a full fields clause to filter results', async function () {
  1317. const schema = createSchema();
  1318. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1319. const rep = schema.getRepository('model');
  1320. const created = await rep.create({foo: 10, bar: 20, baz: 30});
  1321. const id = created[DEF_PK];
  1322. const patched = await rep.patchById(
  1323. id,
  1324. {foo: 15, bar: 25, baz: 35},
  1325. {fields: ['foo', 'bar']},
  1326. );
  1327. expect(patched).to.be.eql({[DEF_PK]: id, foo: 15, bar: 25});
  1328. const oid = new ObjectId(id);
  1329. const rawData = await MDB_CLIENT.db()
  1330. .collection('model')
  1331. .findOne({_id: oid});
  1332. expect(rawData).to.be.eql({_id: oid, foo: 15, bar: 25, baz: 35});
  1333. });
  1334. it('a fields clause uses property names instead of column names', async function () {
  1335. const schema = createSchema();
  1336. schema.defineModel({
  1337. name: 'model',
  1338. datasource: 'mongodb',
  1339. properties: {
  1340. foo: {
  1341. type: DataType.NUMBER,
  1342. columnName: 'fooCol',
  1343. },
  1344. bar: {
  1345. type: DataType.NUMBER,
  1346. columnName: 'barCol',
  1347. },
  1348. baz: {
  1349. type: DataType.NUMBER,
  1350. columnName: 'bazCol',
  1351. },
  1352. },
  1353. });
  1354. const rep = schema.getRepository('model');
  1355. const created = await rep.create(
  1356. {foo: 10, bar: 20, baz: 30},
  1357. {fields: ['fooCol', 'barCol']},
  1358. );
  1359. const id = created[DEF_PK];
  1360. const patched = await rep.patchById(
  1361. id,
  1362. {foo: 15, bar: 25, baz: 35},
  1363. {fields: ['fooCol', 'barCol']},
  1364. );
  1365. expect(patched).to.be.eql({[DEF_PK]: patched[DEF_PK]});
  1366. const oid = new ObjectId(id);
  1367. const rawData = await MDB_CLIENT.db()
  1368. .collection('model')
  1369. .findOne({_id: oid});
  1370. expect(rawData).to.be.eql({_id: oid, fooCol: 15, barCol: 25, bazCol: 35});
  1371. });
  1372. });
  1373. describe('find', function () {
  1374. it('returns an empty array', async function () {
  1375. const schema = createSchema();
  1376. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1377. const rep = schema.getRepository('model');
  1378. const result = await rep.find();
  1379. expect(result).to.be.empty;
  1380. expect(result).to.be.instanceOf(Array);
  1381. });
  1382. it('returns all items', async function () {
  1383. const schema = createSchema();
  1384. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1385. const rep = schema.getRepository('model');
  1386. const doc1 = await rep.create({foo: 1});
  1387. const doc2 = await rep.create({bar: 2});
  1388. const doc3 = await rep.create({baz: 3});
  1389. const result = await rep.find();
  1390. expect(result).to.be.eql([doc1, doc2, doc3]);
  1391. });
  1392. it('uses a short fields clause to filter results', async function () {
  1393. const schema = createSchema();
  1394. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1395. const rep = schema.getRepository('model');
  1396. const created1 = await rep.create({foo: 10, bar: 20});
  1397. const created2 = await rep.create({foo: 20, bar: 30});
  1398. const id1 = created1[DEF_PK];
  1399. const id2 = created2[DEF_PK];
  1400. const result = await rep.find({fields: 'foo'});
  1401. expect(result).to.be.eql([
  1402. {[DEF_PK]: id1, foo: 10},
  1403. {[DEF_PK]: id2, foo: 20},
  1404. ]);
  1405. });
  1406. it('uses a full fields clause to filter results', async function () {
  1407. const schema = createSchema();
  1408. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1409. const rep = schema.getRepository('model');
  1410. const created1 = await rep.create({foo: 10, bar: 20, baz: 30});
  1411. const created2 = await rep.create({foo: 20, bar: 30, baz: 40});
  1412. const id1 = created1[DEF_PK];
  1413. const id2 = created2[DEF_PK];
  1414. const result = await rep.find({fields: ['foo', 'bar']});
  1415. expect(result).to.be.eql([
  1416. {[DEF_PK]: id1, foo: 10, bar: 20},
  1417. {[DEF_PK]: id2, foo: 20, bar: 30},
  1418. ]);
  1419. });
  1420. it('a fields clause uses property names instead of column names', async function () {
  1421. const schema = createSchema();
  1422. schema.defineModel({
  1423. name: 'model',
  1424. datasource: 'mongodb',
  1425. properties: {
  1426. foo: {
  1427. type: DataType.NUMBER,
  1428. columnName: 'fooCol',
  1429. },
  1430. bar: {
  1431. type: DataType.NUMBER,
  1432. columnName: 'barCol',
  1433. },
  1434. baz: {
  1435. type: DataType.NUMBER,
  1436. columnName: 'bazCol',
  1437. },
  1438. },
  1439. });
  1440. const rep = schema.getRepository('model');
  1441. const created1 = await rep.create({foo: 10, bar: 20, baz: 30});
  1442. const created2 = await rep.create({foo: 20, bar: 30, baz: 40});
  1443. const id1 = created1[DEF_PK];
  1444. const id2 = created2[DEF_PK];
  1445. const result = await rep.find({fields: ['fooCol', 'barCol']});
  1446. expect(result).to.be.eql([{[DEF_PK]: id1}, {[DEF_PK]: id2}]);
  1447. });
  1448. it('uses a short order clause to sort results', async function () {
  1449. const schema = createSchema();
  1450. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1451. const rep = schema.getRepository('model');
  1452. const created1 = await rep.create({foo: 20});
  1453. const created2 = await rep.create({foo: 5});
  1454. const created3 = await rep.create({foo: 10});
  1455. const result1 = await rep.find({order: 'foo'});
  1456. const result2 = await rep.find({order: 'foo ASC'});
  1457. const result3 = await rep.find({order: 'foo DESC'});
  1458. expect(result1).to.be.eql([
  1459. {[DEF_PK]: created2[DEF_PK], foo: 5},
  1460. {[DEF_PK]: created3[DEF_PK], foo: 10},
  1461. {[DEF_PK]: created1[DEF_PK], foo: 20},
  1462. ]);
  1463. expect(result2).to.be.eql([
  1464. {[DEF_PK]: created2[DEF_PK], foo: 5},
  1465. {[DEF_PK]: created3[DEF_PK], foo: 10},
  1466. {[DEF_PK]: created1[DEF_PK], foo: 20},
  1467. ]);
  1468. expect(result3).to.be.eql([
  1469. {[DEF_PK]: created1[DEF_PK], foo: 20},
  1470. {[DEF_PK]: created3[DEF_PK], foo: 10},
  1471. {[DEF_PK]: created2[DEF_PK], foo: 5},
  1472. ]);
  1473. });
  1474. it('uses a full order clause to sort results', async function () {
  1475. const schema = createSchema();
  1476. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1477. const rep = schema.getRepository('model');
  1478. const created1 = await rep.create({foo: 20, bar: 'b'});
  1479. const created2 = await rep.create({foo: 5, bar: 'b'});
  1480. const created3 = await rep.create({foo: 10, bar: 'a'});
  1481. const result1 = await rep.find({order: ['bar DESC', 'foo']});
  1482. const result2 = await rep.find({order: ['bar', 'foo ASC']});
  1483. expect(result1).to.be.eql([
  1484. {[DEF_PK]: created2[DEF_PK], foo: 5, bar: 'b'},
  1485. {[DEF_PK]: created1[DEF_PK], foo: 20, bar: 'b'},
  1486. {[DEF_PK]: created3[DEF_PK], foo: 10, bar: 'a'},
  1487. ]);
  1488. expect(result2).to.be.eql([
  1489. {[DEF_PK]: created3[DEF_PK], foo: 10, bar: 'a'},
  1490. {[DEF_PK]: created2[DEF_PK], foo: 5, bar: 'b'},
  1491. {[DEF_PK]: created1[DEF_PK], foo: 20, bar: 'b'},
  1492. ]);
  1493. });
  1494. it('an order clause uses property names instead of column names', async function () {
  1495. const schema = createSchema();
  1496. schema.defineModel({
  1497. name: 'model',
  1498. datasource: 'mongodb',
  1499. properties: {
  1500. foo: {
  1501. type: DataType.NUMBER,
  1502. columnName: 'fooCol',
  1503. },
  1504. bar: {
  1505. type: DataType.STRING,
  1506. columnName: 'barCol',
  1507. },
  1508. },
  1509. });
  1510. const rep = schema.getRepository('model');
  1511. const created1 = await rep.create({foo: 20, bar: 'b'});
  1512. const created2 = await rep.create({foo: 5, bar: 'b'});
  1513. const created3 = await rep.create({foo: 10, bar: 'a'});
  1514. const result1 = await rep.find({order: ['bar DESC', 'foo']});
  1515. const result2 = await rep.find({order: ['bar', 'foo ASC']});
  1516. expect(result1).to.be.eql([
  1517. {[DEF_PK]: created2[DEF_PK], foo: 5, bar: 'b'},
  1518. {[DEF_PK]: created1[DEF_PK], foo: 20, bar: 'b'},
  1519. {[DEF_PK]: created3[DEF_PK], foo: 10, bar: 'a'},
  1520. ]);
  1521. expect(result2).to.be.eql([
  1522. {[DEF_PK]: created3[DEF_PK], foo: 10, bar: 'a'},
  1523. {[DEF_PK]: created2[DEF_PK], foo: 5, bar: 'b'},
  1524. {[DEF_PK]: created1[DEF_PK], foo: 20, bar: 'b'},
  1525. ]);
  1526. });
  1527. it('uses a limit clause to filter results', async function () {
  1528. const schema = createSchema();
  1529. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1530. const rep = schema.getRepository('model');
  1531. const created1 = await rep.create({foo: 10});
  1532. const created2 = await rep.create({foo: 20});
  1533. await rep.create({foo: 30});
  1534. const result = await rep.find({limit: 2});
  1535. expect(result).to.be.eql([created1, created2]);
  1536. });
  1537. it('uses a skip clause to filter results', async function () {
  1538. const schema = createSchema();
  1539. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1540. const rep = schema.getRepository('model');
  1541. await rep.create({foo: 10});
  1542. const created2 = await rep.create({foo: 20});
  1543. const created3 = await rep.create({foo: 30});
  1544. const result = await rep.find({skip: 1});
  1545. expect(result).to.be.eql([created2, created3]);
  1546. });
  1547. describe('uses a where clause to filter results', function () {
  1548. it('matches by a document subset', async function () {
  1549. const schema = createSchema();
  1550. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1551. const rep = schema.getRepository('model');
  1552. const created1 = await rep.create({foo: 5, bar: 'b'});
  1553. const created2 = await rep.create({foo: 10, bar: 'a'});
  1554. const result1 = await rep.find({where: {foo: 10}});
  1555. const result2 = await rep.find({where: {foo: 5, bar: 'b'}});
  1556. expect(result1).to.be.eql([
  1557. {
  1558. [DEF_PK]: created2[DEF_PK],
  1559. foo: 10,
  1560. bar: 'a',
  1561. },
  1562. ]);
  1563. expect(result2).to.be.eql([
  1564. {
  1565. [DEF_PK]: created1[DEF_PK],
  1566. foo: 5,
  1567. bar: 'b',
  1568. },
  1569. ]);
  1570. });
  1571. it('matches by the "eq" operator', async function () {
  1572. const schema = createSchema();
  1573. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1574. const rep = schema.getRepository('model');
  1575. await rep.create({foo: 5});
  1576. const created2 = await rep.create({foo: 10});
  1577. const created3 = await rep.create({foo: 10});
  1578. const result = await rep.find({where: {foo: {eq: 10}}});
  1579. expect(result).to.be.eql([
  1580. {[DEF_PK]: created2[DEF_PK], foo: 10},
  1581. {[DEF_PK]: created3[DEF_PK], foo: 10},
  1582. ]);
  1583. });
  1584. it('matches by the "neq" operator', async function () {
  1585. const schema = createSchema();
  1586. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1587. const rep = schema.getRepository('model');
  1588. const created1 = await rep.create({foo: 5});
  1589. await rep.create({foo: 10});
  1590. await rep.create({foo: 10});
  1591. const result = await rep.find({where: {foo: {neq: 10}}});
  1592. expect(result).to.be.eql([{[DEF_PK]: created1[DEF_PK], foo: 5}]);
  1593. });
  1594. it('matches by the "gt" operator', async function () {
  1595. const schema = createSchema();
  1596. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1597. const rep = schema.getRepository('model');
  1598. await rep.create({foo: 5});
  1599. await rep.create({foo: 10});
  1600. const created3 = await rep.create({foo: 15});
  1601. const result = await rep.find({where: {foo: {gt: 10}}});
  1602. expect(result).to.be.eql([{[DEF_PK]: created3[DEF_PK], foo: 15}]);
  1603. });
  1604. it('matches by the "lt" operator', async function () {
  1605. const schema = createSchema();
  1606. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1607. const rep = schema.getRepository('model');
  1608. const created1 = await rep.create({foo: 5});
  1609. await rep.create({foo: 10});
  1610. await rep.create({foo: 15});
  1611. const result = await rep.find({where: {foo: {lt: 10}}});
  1612. expect(result).to.be.eql([{[DEF_PK]: created1[DEF_PK], foo: 5}]);
  1613. });
  1614. it('matches by the "gte" operator', async function () {
  1615. const schema = createSchema();
  1616. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1617. const rep = schema.getRepository('model');
  1618. await rep.create({foo: 5});
  1619. const created2 = await rep.create({foo: 10});
  1620. const created3 = await rep.create({foo: 15});
  1621. const result = await rep.find({where: {foo: {gte: 10}}});
  1622. expect(result).to.be.eql([
  1623. {[DEF_PK]: created2[DEF_PK], foo: 10},
  1624. {[DEF_PK]: created3[DEF_PK], foo: 15},
  1625. ]);
  1626. });
  1627. it('matches by the "lte" operator', async function () {
  1628. const schema = createSchema();
  1629. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1630. const rep = schema.getRepository('model');
  1631. const created1 = await rep.create({foo: 5});
  1632. const created2 = await rep.create({foo: 10});
  1633. await rep.create({foo: 15});
  1634. const result = await rep.find({where: {foo: {lte: 10}}});
  1635. expect(result).to.be.eql([
  1636. {[DEF_PK]: created1[DEF_PK], foo: 5},
  1637. {[DEF_PK]: created2[DEF_PK], foo: 10},
  1638. ]);
  1639. });
  1640. it('matches by the "inq" operator', async function () {
  1641. const schema = createSchema();
  1642. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1643. const rep = schema.getRepository('model');
  1644. const created1 = await rep.create({foo: 5});
  1645. const created2 = await rep.create({foo: 10});
  1646. await rep.create({foo: 15});
  1647. const result = await rep.find({where: {foo: {inq: [5, 10]}}});
  1648. expect(result).to.be.eql([
  1649. {[DEF_PK]: created1[DEF_PK], foo: 5},
  1650. {[DEF_PK]: created2[DEF_PK], foo: 10},
  1651. ]);
  1652. });
  1653. it('matches by the "nin" operator', async function () {
  1654. const schema = createSchema();
  1655. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1656. const rep = schema.getRepository('model');
  1657. await rep.create({foo: 5});
  1658. await rep.create({foo: 10});
  1659. const created3 = await rep.create({foo: 15});
  1660. const result = await rep.find({where: {foo: {nin: [5, 10]}}});
  1661. expect(result).to.be.eql([{[DEF_PK]: created3[DEF_PK], foo: 15}]);
  1662. });
  1663. it('matches by the "between" operator', async function () {
  1664. const schema = createSchema();
  1665. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1666. const rep = schema.getRepository('model');
  1667. await rep.create({foo: 5});
  1668. const created2 = await rep.create({foo: 10});
  1669. const created3 = await rep.create({foo: 15});
  1670. await rep.create({foo: 20});
  1671. const result = await rep.find({where: {foo: {between: [9, 16]}}});
  1672. expect(result).to.be.eql([
  1673. {[DEF_PK]: created2[DEF_PK], foo: 10},
  1674. {[DEF_PK]: created3[DEF_PK], foo: 15},
  1675. ]);
  1676. });
  1677. it('matches by the "exists" operator', async function () {
  1678. const schema = createSchema();
  1679. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1680. const rep = schema.getRepository('model');
  1681. const created1 = await rep.create({});
  1682. const created2 = await rep.create({foo: undefined});
  1683. const created3 = await rep.create({foo: null});
  1684. const created4 = await rep.create({foo: 10});
  1685. const result1 = await rep.find({where: {foo: {exists: true}}});
  1686. const result2 = await rep.find({where: {foo: {exists: false}}});
  1687. expect(result1).to.be.eql([
  1688. {[DEF_PK]: created2[DEF_PK], foo: null},
  1689. {[DEF_PK]: created3[DEF_PK], foo: null},
  1690. {[DEF_PK]: created4[DEF_PK], foo: 10},
  1691. ]);
  1692. expect(result2).to.be.eql([{[DEF_PK]: created1[DEF_PK]}]);
  1693. });
  1694. it('matches by the "like" operator', async function () {
  1695. const schema = createSchema();
  1696. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1697. const rep = schema.getRepository('model');
  1698. await rep.create({foo: 'lorem ipsum'});
  1699. const created2 = await rep.create({foo: 'dolor sit amet'});
  1700. await rep.create({foo: 'DOLOR SIT AMET'});
  1701. const created4 = await rep.create({foo: 'sit amet'});
  1702. const result = await rep.find({where: {foo: {like: 'sit amet'}}});
  1703. expect(result).to.be.eql([
  1704. {[DEF_PK]: created2[DEF_PK], foo: 'dolor sit amet'},
  1705. {[DEF_PK]: created4[DEF_PK], foo: 'sit amet'},
  1706. ]);
  1707. });
  1708. it('matches by the "ilike" operator', async function () {
  1709. const schema = createSchema();
  1710. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1711. const rep = schema.getRepository('model');
  1712. await rep.create({foo: 'lorem ipsum'});
  1713. const created2 = await rep.create({foo: 'dolor sit amet'});
  1714. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  1715. const created4 = await rep.create({foo: 'sit amet'});
  1716. const result = await rep.find({where: {foo: {ilike: 'sit amet'}}});
  1717. expect(result).to.be.eql([
  1718. {[DEF_PK]: created2[DEF_PK], foo: 'dolor sit amet'},
  1719. {[DEF_PK]: created3[DEF_PK], foo: 'DOLOR SIT AMET'},
  1720. {[DEF_PK]: created4[DEF_PK], foo: 'sit amet'},
  1721. ]);
  1722. });
  1723. it('matches by the "nlike" operator', async function () {
  1724. const schema = createSchema();
  1725. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1726. const rep = schema.getRepository('model');
  1727. const created1 = await rep.create({foo: 'lorem ipsum'});
  1728. await rep.create({foo: 'dolor sit amet'});
  1729. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  1730. await rep.create({foo: 'sit amet'});
  1731. const result = await rep.find({where: {foo: {nlike: 'sit amet'}}});
  1732. expect(result).to.be.eql([
  1733. {[DEF_PK]: created1[DEF_PK], foo: 'lorem ipsum'},
  1734. {[DEF_PK]: created3[DEF_PK], foo: 'DOLOR SIT AMET'},
  1735. ]);
  1736. });
  1737. it('matches by the "nilike" operator', async function () {
  1738. const schema = createSchema();
  1739. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1740. const rep = schema.getRepository('model');
  1741. const created1 = await rep.create({foo: 'lorem ipsum'});
  1742. await rep.create({foo: 'dolor sit amet'});
  1743. await rep.create({foo: 'DOLOR SIT AMET'});
  1744. await rep.create({foo: 'sit amet'});
  1745. const result = await rep.find({where: {foo: {nilike: 'sit amet'}}});
  1746. expect(result).to.be.eql([
  1747. {[DEF_PK]: created1[DEF_PK], foo: 'lorem ipsum'},
  1748. ]);
  1749. });
  1750. it('matches by the "regexp" operator', async function () {
  1751. const schema = createSchema();
  1752. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1753. const rep = schema.getRepository('model');
  1754. await rep.create({foo: 'lorem ipsum'});
  1755. const created2 = await rep.create({foo: 'dolor sit amet'});
  1756. await rep.create({foo: 'DOLOR SIT AMET'});
  1757. const created4 = await rep.create({foo: 'sit amet'});
  1758. const result = await rep.find({where: {foo: {regexp: 'sit am+'}}});
  1759. expect(result).to.be.eql([
  1760. {[DEF_PK]: created2[DEF_PK], foo: 'dolor sit amet'},
  1761. {[DEF_PK]: created4[DEF_PK], foo: 'sit amet'},
  1762. ]);
  1763. });
  1764. it('matches by the "regexp" operator with flags', async function () {
  1765. const schema = createSchema();
  1766. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1767. const rep = schema.getRepository('model');
  1768. await rep.create({foo: 'lorem ipsum'});
  1769. const created2 = await rep.create({foo: 'dolor sit amet'});
  1770. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  1771. const created4 = await rep.create({foo: 'sit amet'});
  1772. const result = await rep.find({
  1773. where: {
  1774. foo: {regexp: 'sit am+', flags: 'i'},
  1775. },
  1776. });
  1777. expect(result).to.be.eql([
  1778. {[DEF_PK]: created2[DEF_PK], foo: 'dolor sit amet'},
  1779. {[DEF_PK]: created3[DEF_PK], foo: 'DOLOR SIT AMET'},
  1780. {[DEF_PK]: created4[DEF_PK], foo: 'sit amet'},
  1781. ]);
  1782. });
  1783. });
  1784. });
  1785. describe('findById', function () {
  1786. it('throws an error if a given identifier does not exist', async function () {
  1787. const schema = createSchema();
  1788. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1789. const rep = schema.getRepository('model');
  1790. const oid = new ObjectId();
  1791. const promise = rep.findById(oid);
  1792. await expect(promise).to.be.rejectedWith(
  1793. format('Identifier "%s" is not found.', oid),
  1794. );
  1795. });
  1796. it('uses a short fields clause to filter results', async function () {
  1797. const schema = createSchema();
  1798. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1799. const rep = schema.getRepository('model');
  1800. const created = await rep.create({foo: 10, bar: 20});
  1801. const id = created[DEF_PK];
  1802. const result = await rep.findById(id, {fields: 'foo'});
  1803. expect(result).to.be.eql({[DEF_PK]: id, foo: 10});
  1804. });
  1805. it('uses a full fields clause to filter results', async function () {
  1806. const schema = createSchema();
  1807. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1808. const rep = schema.getRepository('model');
  1809. const created = await rep.create({foo: 10, bar: 20, baz: 30});
  1810. const id = created[DEF_PK];
  1811. const result = await rep.findById(id, {fields: ['foo', 'bar']});
  1812. expect(result).to.be.eql({[DEF_PK]: id, foo: 10, bar: 20});
  1813. });
  1814. });
  1815. describe('delete', function () {
  1816. it('removes all table items and returns their number', async function () {
  1817. const schema = createSchema();
  1818. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1819. const rep = schema.getRepository('model');
  1820. await rep.create({foo: 1});
  1821. await rep.create({foo: 2});
  1822. await rep.create({foo: 3});
  1823. const result = await rep.delete();
  1824. expect(result).to.be.eql(3);
  1825. const rawData = await MDB_CLIENT.db()
  1826. .collection('model')
  1827. .find()
  1828. .toArray();
  1829. expect(rawData).to.be.empty;
  1830. });
  1831. describe('removes by a where clause', function () {
  1832. it('removes by a document subset', async function () {
  1833. const schema = createSchema();
  1834. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1835. const rep = schema.getRepository('model');
  1836. const created1 = await rep.create({foo: 5});
  1837. await rep.create({foo: 10});
  1838. const result = await rep.delete({foo: 10});
  1839. expect(result).to.be.eq(1);
  1840. const rawData = await MDB_CLIENT.db()
  1841. .collection('model')
  1842. .find()
  1843. .toArray();
  1844. expect(rawData).to.be.eql([
  1845. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  1846. ]);
  1847. });
  1848. it('matches by the "eq" operator', async function () {
  1849. const schema = createSchema();
  1850. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1851. const rep = schema.getRepository('model');
  1852. const created1 = await rep.create({foo: 5});
  1853. await rep.create({foo: 10});
  1854. await rep.create({foo: 10});
  1855. const result = await rep.delete({foo: {eq: 10}});
  1856. expect(result).to.be.eq(2);
  1857. const rawData = await MDB_CLIENT.db()
  1858. .collection('model')
  1859. .find()
  1860. .toArray();
  1861. expect(rawData).to.be.eql([
  1862. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  1863. ]);
  1864. });
  1865. it('matches by the "neq" operator', async function () {
  1866. const schema = createSchema();
  1867. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1868. const rep = schema.getRepository('model');
  1869. await rep.create({foo: 5});
  1870. await rep.create({foo: 5});
  1871. const created3 = await rep.create({foo: 10});
  1872. const result = await rep.delete({foo: {neq: 10}});
  1873. expect(result).to.be.eq(2);
  1874. const rawData = await MDB_CLIENT.db()
  1875. .collection('model')
  1876. .find()
  1877. .toArray();
  1878. expect(rawData).to.be.eql([
  1879. {_id: new ObjectId(created3[DEF_PK]), foo: 10},
  1880. ]);
  1881. });
  1882. it('matches by the "gt" operator', async function () {
  1883. const schema = createSchema();
  1884. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1885. const rep = schema.getRepository('model');
  1886. const created1 = await rep.create({foo: 5});
  1887. const created2 = await rep.create({foo: 10});
  1888. await rep.create({foo: 15});
  1889. const result = await rep.delete({foo: {gt: 10}});
  1890. expect(result).to.be.eq(1);
  1891. const rawData = await MDB_CLIENT.db()
  1892. .collection('model')
  1893. .find()
  1894. .toArray();
  1895. expect(rawData).to.be.eql([
  1896. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  1897. {_id: new ObjectId(created2[DEF_PK]), foo: 10},
  1898. ]);
  1899. });
  1900. it('matches by the "lt" operator', async function () {
  1901. const schema = createSchema();
  1902. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1903. const rep = schema.getRepository('model');
  1904. await rep.create({foo: 5});
  1905. const created2 = await rep.create({foo: 10});
  1906. const created3 = await rep.create({foo: 15});
  1907. const result = await rep.delete({foo: {lt: 10}});
  1908. expect(result).to.be.eq(1);
  1909. const rawData = await MDB_CLIENT.db()
  1910. .collection('model')
  1911. .find()
  1912. .toArray();
  1913. expect(rawData).to.be.eql([
  1914. {_id: new ObjectId(created2[DEF_PK]), foo: 10},
  1915. {_id: new ObjectId(created3[DEF_PK]), foo: 15},
  1916. ]);
  1917. });
  1918. it('matches by the "gte" operator', async function () {
  1919. const schema = createSchema();
  1920. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1921. const rep = schema.getRepository('model');
  1922. const created1 = await rep.create({foo: 5});
  1923. await rep.create({foo: 10});
  1924. await rep.create({foo: 15});
  1925. const result = await rep.delete({foo: {gte: 10}});
  1926. expect(result).to.be.eq(2);
  1927. const rawData = await MDB_CLIENT.db()
  1928. .collection('model')
  1929. .find()
  1930. .toArray();
  1931. expect(rawData).to.be.eql([
  1932. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  1933. ]);
  1934. });
  1935. it('matches by the "lte" operator', async function () {
  1936. const schema = createSchema();
  1937. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1938. const rep = schema.getRepository('model');
  1939. await rep.create({foo: 5});
  1940. await rep.create({foo: 10});
  1941. const created3 = await rep.create({foo: 15});
  1942. const result = await rep.delete({foo: {lte: 10}});
  1943. expect(result).to.be.eq(2);
  1944. const rawData = await MDB_CLIENT.db()
  1945. .collection('model')
  1946. .find()
  1947. .toArray();
  1948. expect(rawData).to.be.eql([
  1949. {_id: new ObjectId(created3[DEF_PK]), foo: 15},
  1950. ]);
  1951. });
  1952. it('matches by the "inq" operator', async function () {
  1953. const schema = createSchema();
  1954. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1955. const rep = schema.getRepository('model');
  1956. await rep.create({foo: 5});
  1957. await rep.create({foo: 10});
  1958. const created3 = await rep.create({foo: 15});
  1959. const result = await rep.delete({foo: {inq: [5, 10]}});
  1960. expect(result).to.be.eq(2);
  1961. const rawData = await MDB_CLIENT.db()
  1962. .collection('model')
  1963. .find()
  1964. .toArray();
  1965. expect(rawData).to.be.eql([
  1966. {_id: new ObjectId(created3[DEF_PK]), foo: 15},
  1967. ]);
  1968. });
  1969. it('matches by the "nin" operator', async function () {
  1970. const schema = createSchema();
  1971. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1972. const rep = schema.getRepository('model');
  1973. const created1 = await rep.create({foo: 5});
  1974. const created2 = await rep.create({foo: 10});
  1975. await rep.create({foo: 15});
  1976. const result = await rep.delete({foo: {nin: [5, 10]}});
  1977. expect(result).to.be.eq(1);
  1978. const rawData = await MDB_CLIENT.db()
  1979. .collection('model')
  1980. .find()
  1981. .toArray();
  1982. expect(rawData).to.be.eql([
  1983. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  1984. {_id: new ObjectId(created2[DEF_PK]), foo: 10},
  1985. ]);
  1986. });
  1987. it('matches by the "between" operator', async function () {
  1988. const schema = createSchema();
  1989. schema.defineModel({name: 'model', datasource: 'mongodb'});
  1990. const rep = schema.getRepository('model');
  1991. const created1 = await rep.create({foo: 5});
  1992. await rep.create({foo: 10});
  1993. await rep.create({foo: 15});
  1994. const created4 = await rep.create({foo: 20});
  1995. const result = await rep.delete({foo: {between: [9, 16]}});
  1996. expect(result).to.be.eq(2);
  1997. const rawData = await MDB_CLIENT.db()
  1998. .collection('model')
  1999. .find()
  2000. .toArray();
  2001. expect(rawData).to.be.eql([
  2002. {_id: new ObjectId(created1[DEF_PK]), foo: 5},
  2003. {_id: new ObjectId(created4[DEF_PK]), foo: 20},
  2004. ]);
  2005. });
  2006. it('matches by the "exists" operator', async function () {
  2007. const schema = createSchema();
  2008. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2009. const rep = schema.getRepository('model');
  2010. const created1 = await rep.create({});
  2011. await rep.create({foo: undefined});
  2012. await rep.create({foo: null});
  2013. await rep.create({foo: 10});
  2014. const result = await rep.delete({foo: {exists: true}});
  2015. expect(result).to.be.eq(3);
  2016. const rawData = await MDB_CLIENT.db()
  2017. .collection('model')
  2018. .find()
  2019. .toArray();
  2020. expect(rawData).to.be.eql([{_id: new ObjectId(created1[DEF_PK])}]);
  2021. });
  2022. it('matches by the "like" operator', async function () {
  2023. const schema = createSchema();
  2024. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2025. const rep = schema.getRepository('model');
  2026. const created1 = await rep.create({foo: 'lorem ipsum'});
  2027. await rep.create({foo: 'dolor sit amet'});
  2028. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  2029. await rep.create({foo: 'sit amet'});
  2030. const result = await rep.delete({foo: {like: 'sit amet'}});
  2031. expect(result).to.be.eq(2);
  2032. const rawData = await MDB_CLIENT.db()
  2033. .collection('model')
  2034. .find()
  2035. .toArray();
  2036. expect(rawData).to.be.eql([
  2037. {_id: new ObjectId(created1[DEF_PK]), foo: 'lorem ipsum'},
  2038. {_id: new ObjectId(created3[DEF_PK]), foo: 'DOLOR SIT AMET'},
  2039. ]);
  2040. });
  2041. it('matches by the "nlike" operator', async function () {
  2042. const schema = createSchema();
  2043. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2044. const rep = schema.getRepository('model');
  2045. await rep.create({foo: 'lorem ipsum'});
  2046. const created2 = await rep.create({foo: 'dolor sit amet'});
  2047. await rep.create({foo: 'DOLOR SIT AMET'});
  2048. const created4 = await rep.create({foo: 'sit amet'});
  2049. const result = await rep.delete({foo: {nlike: 'sit amet'}});
  2050. expect(result).to.be.eq(2);
  2051. const rawData = await MDB_CLIENT.db()
  2052. .collection('model')
  2053. .find()
  2054. .toArray();
  2055. expect(rawData).to.be.eql([
  2056. {_id: new ObjectId(created2[DEF_PK]), foo: 'dolor sit amet'},
  2057. {_id: new ObjectId(created4[DEF_PK]), foo: 'sit amet'},
  2058. ]);
  2059. });
  2060. it('matches by the "ilike" operator', async function () {
  2061. const schema = createSchema();
  2062. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2063. const rep = schema.getRepository('model');
  2064. const created1 = await rep.create({foo: 'lorem ipsum'});
  2065. await rep.create({foo: 'dolor sit amet'});
  2066. await rep.create({foo: 'DOLOR SIT AMET'});
  2067. await rep.create({foo: 'sit amet'});
  2068. const result = await rep.delete({foo: {ilike: 'sit amet'}});
  2069. expect(result).to.be.eq(3);
  2070. const rawData = await MDB_CLIENT.db()
  2071. .collection('model')
  2072. .find()
  2073. .toArray();
  2074. expect(rawData).to.be.eql([
  2075. {_id: new ObjectId(created1[DEF_PK]), foo: 'lorem ipsum'},
  2076. ]);
  2077. });
  2078. it('matches by the "nilike" operator', async function () {
  2079. const schema = createSchema();
  2080. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2081. const rep = schema.getRepository('model');
  2082. await rep.create({foo: 'lorem ipsum'});
  2083. const created2 = await rep.create({foo: 'dolor sit amet'});
  2084. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  2085. const created4 = await rep.create({foo: 'sit amet'});
  2086. const result = await rep.delete({foo: {nilike: 'sit amet'}});
  2087. expect(result).to.be.eq(1);
  2088. const rawData = await MDB_CLIENT.db()
  2089. .collection('model')
  2090. .find()
  2091. .toArray();
  2092. expect(rawData).to.be.eql([
  2093. {_id: new ObjectId(created2[DEF_PK]), foo: 'dolor sit amet'},
  2094. {_id: new ObjectId(created3[DEF_PK]), foo: 'DOLOR SIT AMET'},
  2095. {_id: new ObjectId(created4[DEF_PK]), foo: 'sit amet'},
  2096. ]);
  2097. });
  2098. it('matches by the "regexp" operator', async function () {
  2099. const schema = createSchema();
  2100. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2101. const rep = schema.getRepository('model');
  2102. const created1 = await rep.create({foo: 'lorem ipsum'});
  2103. await rep.create({foo: 'dolor sit amet'});
  2104. const created3 = await rep.create({foo: 'DOLOR SIT AMET'});
  2105. await rep.create({foo: 'sit amet'});
  2106. const result = await rep.delete({foo: {regexp: 'sit am+'}});
  2107. expect(result).to.be.eq(2);
  2108. const rawData = await MDB_CLIENT.db()
  2109. .collection('model')
  2110. .find()
  2111. .toArray();
  2112. expect(rawData).to.be.eql([
  2113. {_id: new ObjectId(created1[DEF_PK]), foo: 'lorem ipsum'},
  2114. {_id: new ObjectId(created3[DEF_PK]), foo: 'DOLOR SIT AMET'},
  2115. ]);
  2116. });
  2117. it('matches by the "regexp" operator with flags', async function () {
  2118. const schema = createSchema();
  2119. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2120. const rep = schema.getRepository('model');
  2121. const created1 = await rep.create({foo: 'lorem ipsum'});
  2122. await rep.create({foo: 'dolor sit amet'});
  2123. await rep.create({foo: 'DOLOR SIT AMET'});
  2124. await rep.create({foo: 'sit amet'});
  2125. const result = await rep.delete({foo: {regexp: 'sit am+', flags: 'i'}});
  2126. expect(result).to.be.eq(3);
  2127. const rawData = await MDB_CLIENT.db()
  2128. .collection('model')
  2129. .find()
  2130. .toArray();
  2131. expect(rawData).to.be.eql([
  2132. {_id: new ObjectId(created1[DEF_PK]), foo: 'lorem ipsum'},
  2133. ]);
  2134. });
  2135. });
  2136. });
  2137. describe('deleteById', function () {
  2138. it('returns false if a given identifier is not exist', async function () {
  2139. const schema = createSchema();
  2140. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2141. const rep = schema.getRepository('model');
  2142. const oid = new ObjectId();
  2143. const result = await rep.deleteById(oid);
  2144. expect(result).to.be.false;
  2145. });
  2146. it('returns true if an item has removed by a given identifier', async function () {
  2147. const schema = createSchema();
  2148. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2149. const rep = schema.getRepository('model');
  2150. const oid = new ObjectId();
  2151. await rep.create({[DEF_PK]: oid});
  2152. const result = await rep.deleteById(oid);
  2153. expect(result).to.be.true;
  2154. const rawData = await MDB_CLIENT.db()
  2155. .collection('model')
  2156. .find()
  2157. .toArray();
  2158. expect(rawData).to.be.empty;
  2159. });
  2160. });
  2161. describe('exists', function () {
  2162. it('returns false if a given identifier is not exist', async function () {
  2163. const schema = createSchema();
  2164. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2165. const rep = schema.getRepository('model');
  2166. const oid = new ObjectId();
  2167. const result = await rep.exists(oid);
  2168. expect(result).to.be.false;
  2169. });
  2170. it('returns true if a given identifier is exist', async function () {
  2171. const schema = createSchema();
  2172. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2173. const rep = schema.getRepository('model');
  2174. const oid = new ObjectId();
  2175. await rep.create({[DEF_PK]: oid});
  2176. const result = await rep.exists(oid);
  2177. expect(result).to.be.true;
  2178. });
  2179. });
  2180. describe('count', function () {
  2181. it('returns zero if nothing to count', async function () {
  2182. const schema = createSchema();
  2183. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2184. const rep = schema.getRepository('model');
  2185. const result = await rep.count();
  2186. expect(result).to.be.eq(0);
  2187. });
  2188. it('returns a number of table items', async function () {
  2189. const schema = createSchema();
  2190. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2191. const rep = schema.getRepository('model');
  2192. await rep.create({});
  2193. await rep.create({});
  2194. await rep.create({});
  2195. const result = await rep.count();
  2196. expect(result).to.be.eq(3);
  2197. });
  2198. describe('uses a where clause to count items', function () {
  2199. it('matches by a document subset', async function () {
  2200. const schema = createSchema();
  2201. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2202. const rep = schema.getRepository('model');
  2203. await rep.create({foo: 'a'});
  2204. await rep.create({foo: 'b'});
  2205. await rep.create({foo: 'b'});
  2206. const result = await rep.count({foo: 'b'});
  2207. expect(result).to.be.eql(2);
  2208. });
  2209. it('matches by the "eq" operator', async function () {
  2210. const schema = createSchema();
  2211. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2212. const rep = schema.getRepository('model');
  2213. await rep.create({foo: 5});
  2214. await rep.create({foo: 10});
  2215. await rep.create({foo: 10});
  2216. const result = await rep.count({foo: {eq: 10}});
  2217. expect(result).to.be.eql(2);
  2218. });
  2219. it('matches by the "neq" operator', async function () {
  2220. const schema = createSchema();
  2221. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2222. const rep = schema.getRepository('model');
  2223. await rep.create({foo: 5});
  2224. await rep.create({foo: 10});
  2225. await rep.create({foo: 10});
  2226. const result = await rep.count({foo: {neq: 10}});
  2227. expect(result).to.be.eq(1);
  2228. });
  2229. it('matches by the "gt" operator', async function () {
  2230. const schema = createSchema();
  2231. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2232. const rep = schema.getRepository('model');
  2233. await rep.create({foo: 5});
  2234. await rep.create({foo: 10});
  2235. await rep.create({foo: 15});
  2236. const result = await rep.count({foo: {gt: 10}});
  2237. expect(result).to.be.eq(1);
  2238. });
  2239. it('matches by the "lt" operator', async function () {
  2240. const schema = createSchema();
  2241. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2242. const rep = schema.getRepository('model');
  2243. await rep.create({foo: 5});
  2244. await rep.create({foo: 10});
  2245. await rep.create({foo: 15});
  2246. const result = await rep.count({foo: {lt: 10}});
  2247. expect(result).to.be.eq(1);
  2248. });
  2249. it('matches by the "gte" operator', async function () {
  2250. const schema = createSchema();
  2251. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2252. const rep = schema.getRepository('model');
  2253. await rep.create({foo: 5});
  2254. await rep.create({foo: 10});
  2255. await rep.create({foo: 15});
  2256. const result = await rep.count({foo: {gte: 10}});
  2257. expect(result).to.be.eq(2);
  2258. });
  2259. it('matches by the "lte" operator', async function () {
  2260. const schema = createSchema();
  2261. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2262. const rep = schema.getRepository('model');
  2263. await rep.create({foo: 5});
  2264. await rep.create({foo: 10});
  2265. await rep.create({foo: 15});
  2266. const result = await rep.count({foo: {lte: 10}});
  2267. expect(result).to.be.eq(2);
  2268. });
  2269. it('matches by the "inq" operator', async function () {
  2270. const schema = createSchema();
  2271. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2272. const rep = schema.getRepository('model');
  2273. await rep.create({foo: 5});
  2274. await rep.create({foo: 10});
  2275. await rep.create({foo: 15});
  2276. const result = await rep.count({foo: {inq: [5, 10]}});
  2277. expect(result).to.be.eq(2);
  2278. });
  2279. it('matches by the "nin" operator', async function () {
  2280. const schema = createSchema();
  2281. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2282. const rep = schema.getRepository('model');
  2283. await rep.create({foo: 5});
  2284. await rep.create({foo: 10});
  2285. await rep.create({foo: 15});
  2286. const result = await rep.count({foo: {nin: [5, 10]}});
  2287. expect(result).to.be.eq(1);
  2288. });
  2289. it('matches by the "between" operator', async function () {
  2290. const schema = createSchema();
  2291. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2292. const rep = schema.getRepository('model');
  2293. await rep.create({foo: 5});
  2294. await rep.create({foo: 10});
  2295. await rep.create({foo: 15});
  2296. await rep.create({foo: 20});
  2297. const result = await rep.count({foo: {between: [9, 16]}});
  2298. expect(result).to.be.eq(2);
  2299. });
  2300. it('matches by the "exists" operator', async function () {
  2301. const schema = createSchema();
  2302. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2303. const rep = schema.getRepository('model');
  2304. await rep.create({});
  2305. await rep.create({foo: undefined});
  2306. await rep.create({foo: null});
  2307. await rep.create({foo: 10});
  2308. const result1 = await rep.count({foo: {exists: true}});
  2309. expect(result1).to.be.eq(3);
  2310. });
  2311. it('matches by the "like" operator', async function () {
  2312. const schema = createSchema();
  2313. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2314. const rep = schema.getRepository('model');
  2315. await rep.create({foo: 'lorem ipsum'});
  2316. await rep.create({foo: 'dolor sit amet'});
  2317. await rep.create({foo: 'DOLOR SIT AMET'});
  2318. await rep.create({foo: 'sit amet'});
  2319. const result = await rep.count({foo: {like: 'sit amet'}});
  2320. expect(result).to.be.eql(2);
  2321. });
  2322. it('matches by the "nlike" operator', async function () {
  2323. const schema = createSchema();
  2324. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2325. const rep = schema.getRepository('model');
  2326. await rep.create({foo: 'lorem ipsum'});
  2327. await rep.create({foo: 'dolor sit amet'});
  2328. await rep.create({foo: 'DOLOR SIT AMET'});
  2329. await rep.create({foo: 'sit amet'});
  2330. const result = await rep.count({foo: {nlike: 'sit amet'}});
  2331. expect(result).to.be.eql(2);
  2332. });
  2333. it('matches by the "ilike" operator', async function () {
  2334. const schema = createSchema();
  2335. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2336. const rep = schema.getRepository('model');
  2337. await rep.create({foo: 'lorem ipsum'});
  2338. await rep.create({foo: 'dolor sit amet'});
  2339. await rep.create({foo: 'DOLOR SIT AMET'});
  2340. await rep.create({foo: 'sit amet'});
  2341. const result = await rep.count({foo: {ilike: 'sit amet'}});
  2342. expect(result).to.be.eql(3);
  2343. });
  2344. it('matches by the "nilike" operator', async function () {
  2345. const schema = createSchema();
  2346. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2347. const rep = schema.getRepository('model');
  2348. await rep.create({foo: 'lorem ipsum'});
  2349. await rep.create({foo: 'dolor sit amet'});
  2350. await rep.create({foo: 'DOLOR SIT AMET'});
  2351. await rep.create({foo: 'sit amet'});
  2352. const result = await rep.count({foo: {nilike: 'sit amet'}});
  2353. expect(result).to.be.eql(1);
  2354. });
  2355. it('matches by the "regexp" operator', async function () {
  2356. const schema = createSchema();
  2357. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2358. const rep = schema.getRepository('model');
  2359. await rep.create({foo: 'lorem ipsum'});
  2360. await rep.create({foo: 'dolor sit amet'});
  2361. await rep.create({foo: 'DOLOR SIT AMET'});
  2362. await rep.create({foo: 'sit amet'});
  2363. const result = await rep.count({foo: {regexp: 'sit am+'}});
  2364. expect(result).to.be.eql(2);
  2365. });
  2366. it('matches by the "regexp" operator with flags', async function () {
  2367. const schema = createSchema();
  2368. schema.defineModel({name: 'model', datasource: 'mongodb'});
  2369. const rep = schema.getRepository('model');
  2370. await rep.create({foo: 'lorem ipsum'});
  2371. await rep.create({foo: 'dolor sit amet'});
  2372. await rep.create({foo: 'DOLOR SIT AMET'});
  2373. await rep.create({foo: 'sit amet'});
  2374. const result = await rep.count({foo: {regexp: 'sit am+', flags: 'i'}});
  2375. expect(result).to.be.eql(3);
  2376. });
  2377. });
  2378. });
  2379. });