spice-couchbase 2.0.43 → 2.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/build/index.js +137 -28
  2. package/package.json +2 -2
  3. package/src/index.js +120 -28
package/build/index.js CHANGED
@@ -36,8 +36,10 @@ if (!Promise.allSettled) {
36
36
  status: "rejected",
37
37
  reason
38
38
  }))));
39
- }
39
+ } // Couchbase lookupIn has a limit of 16 operations per call
40
40
 
41
+
42
+ var LOOKUP_IN_MAX_SPECS = 16;
41
43
  module.exports = class Database {
42
44
  constructor(connection) {
43
45
  var {
@@ -299,12 +301,46 @@ module.exports = class Database {
299
301
  get(doc_id) {
300
302
  var _this8 = this;
301
303
 
304
+ var {
305
+ columns = []
306
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
302
307
  return _asyncToGenerator(function* () {
303
308
  try {
304
- var response = yield (_this8.use_bucket_name ? _this8.connection : _this8.collection).get(doc_id);
305
- return _objectSpread({
309
+ var useLookupIn = columns.length > 0;
310
+ var collection = _this8.use_bucket_name ? _this8.connection : _this8.collection;
311
+
312
+ if (!useLookupIn) {
313
+ var response = yield collection.get(doc_id);
314
+ return _objectSpread({
315
+ id: doc_id
316
+ }, response.content);
317
+ } // Batch columns into chunks of LOOKUP_IN_MAX_SPECS (16)
318
+
319
+
320
+ var value = {
306
321
  id: doc_id
307
- }, response.content);
322
+ };
323
+
324
+ var columnBatches = _.chunk(columns, LOOKUP_IN_MAX_SPECS); // Execute all batch requests in parallel
325
+
326
+
327
+ var batchPromises = columnBatches.map(batch => {
328
+ var specs = batch.map(col => couchbase.LookupInSpec.get(col));
329
+ return collection.lookupIn(doc_id, specs);
330
+ });
331
+ var batchResults = yield Promise.allSettled(batchPromises); // Merge results from all batches
332
+
333
+ batchResults.forEach((result, batchIndex) => {
334
+ if (result.status === "fulfilled" && result.value) {
335
+ var batch = columnBatches[batchIndex];
336
+ batch.forEach((col, colIndex) => {
337
+ if (result.value.content && result.value.content[colIndex]) {
338
+ value[col] = result.value.content[colIndex].value;
339
+ }
340
+ });
341
+ }
342
+ });
343
+ return value;
308
344
  } catch (e) {
309
345
  console.error(e);
310
346
  }
@@ -368,33 +404,106 @@ module.exports = class Database {
368
404
  })();
369
405
  }
370
406
 
371
- multi_get(keys, keep_type) {
407
+ multi_get(keys) {
372
408
  var _this14 = this;
373
409
 
410
+ var {
411
+ keep_type = true,
412
+ columns = []
413
+ } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
374
414
  return _asyncToGenerator(function* () {
375
415
  if (keys.length == 0) {
376
416
  return [];
377
417
  }
378
418
 
379
419
  if (_.isArray(keys) && keys.length > 0) {
380
- var functions = _.map(keys, key => (_this14.use_bucket_name ? _this14.connection : _this14.collection).get(key));
420
+ var useLookupIn = columns.length > 0;
421
+ var collection = _this14.use_bucket_name ? _this14.connection : _this14.collection;
381
422
 
382
- var returned_all = yield Promise.allSettled(functions);
423
+ if (!useLookupIn) {
424
+ // Regular get - no batching needed
425
+ var functions = _.map(keys, key => collection.get(key));
383
426
 
384
- var responses = _.flatten(_.map(returned_all, returned_obj => {
385
- return returned_obj === null || returned_obj === void 0 ? void 0 : returned_obj.value;
386
- }));
427
+ var returned_all = yield Promise.allSettled(functions);
428
+
429
+ var responses = _.flatten(_.map(returned_all, returned_obj => returned_obj === null || returned_obj === void 0 ? void 0 : returned_obj.value));
430
+
431
+ var _final_responses = _.compact(_.map(responses, (res, index) => {
432
+ if (res) {
433
+ var value = res.value;
434
+
435
+ if (!keep_type && value) {
436
+ delete value.type;
437
+ }
387
438
 
388
- return _.compact(_.map(responses, (res, index) => {
389
- if (res) {
390
- if (!keep_type) {
391
- delete res.value.type;
439
+ if (value) {
440
+ value.id = keys[index];
441
+ }
442
+
443
+ return value;
444
+ }
445
+ }));
446
+
447
+ return _final_responses;
448
+ } // lookupIn with batching for columns > 16
449
+
450
+
451
+ var columnBatches = _.chunk(columns, LOOKUP_IN_MAX_SPECS); // For each key, we need to fetch all column batches and merge the results
452
+
453
+
454
+ var keyPromises = _.map(keys,
455
+ /*#__PURE__*/
456
+ function () {
457
+ var _ref = _asyncToGenerator(function* (key) {
458
+ try {
459
+ var value = {
460
+ id: key
461
+ }; // Execute all batch requests for this key in parallel
462
+
463
+ var batchPromises = columnBatches.map(batch => {
464
+ var specs = batch.map(col => couchbase.LookupInSpec.get(col));
465
+ return collection.lookupIn(key, specs);
466
+ });
467
+ var batchResults = yield Promise.allSettled(batchPromises); // Merge results from all batches
468
+
469
+ batchResults.forEach((result, batchIndex) => {
470
+ if (result.status === "fulfilled" && result.value) {
471
+ var batch = columnBatches[batchIndex];
472
+ batch.forEach((col, colIndex) => {
473
+ if (result.value.content && result.value.content[colIndex]) {
474
+ value[col] = result.value.content[colIndex].value;
475
+ }
476
+ });
477
+ }
478
+ });
479
+
480
+ if (!keep_type && value) {
481
+ delete value.type;
482
+ }
483
+
484
+ return value;
485
+ } catch (e) {
486
+ return null;
392
487
  }
488
+ });
393
489
 
394
- res.value.id = keys[index];
395
- return res.value;
490
+ return function (_x) {
491
+ return _ref.apply(this, arguments);
492
+ };
493
+ }());
494
+
495
+ var results = yield Promise.allSettled(keyPromises);
496
+
497
+ var final_responses = _.compact(_.map(results, result => {
498
+ if (result.status === "fulfilled" && result.value) {
499
+ // Only return if we got at least some data beyond just the id
500
+ return Object.keys(result.value).length > 1 ? result.value : null;
396
501
  }
502
+
503
+ return null;
397
504
  }));
505
+
506
+ return final_responses;
398
507
  } else {
399
508
  return [];
400
509
  }
@@ -406,7 +515,7 @@ module.exports = class Database {
406
515
  return new Promise(
407
516
  /*#__PURE__*/
408
517
  function () {
409
- var _ref = _asyncToGenerator(function* (resolve, reject) {
518
+ var _ref2 = _asyncToGenerator(function* (resolve, reject) {
410
519
  var ViewQuery = couchbase.ViewQuery;
411
520
  var query = ViewQuery.from(design_doc, view);
412
521
 
@@ -433,7 +542,7 @@ module.exports = class Database {
433
542
  that.connection.query(query,
434
543
  /*#__PURE__*/
435
544
  function () {
436
- var _ref2 = _asyncToGenerator(function* (err, results, matrix) {
545
+ var _ref3 = _asyncToGenerator(function* (err, results, matrix) {
437
546
  var return_value = [];
438
547
 
439
548
  if (err) {
@@ -456,14 +565,14 @@ module.exports = class Database {
456
565
  }
457
566
  });
458
567
 
459
- return function (_x3, _x4, _x5) {
460
- return _ref2.apply(this, arguments);
568
+ return function (_x4, _x5, _x6) {
569
+ return _ref3.apply(this, arguments);
461
570
  };
462
571
  }());
463
572
  });
464
573
 
465
- return function (_x, _x2) {
466
- return _ref.apply(this, arguments);
574
+ return function (_x2, _x3) {
575
+ return _ref2.apply(this, arguments);
467
576
  };
468
577
  }());
469
578
  }
@@ -567,7 +676,7 @@ module.exports = class Database {
567
676
  return new Promise(
568
677
  /*#__PURE__*/
569
678
  function () {
570
- var _ref3 = _asyncToGenerator(function* (resolve, reject) {
679
+ var _ref4 = _asyncToGenerator(function* (resolve, reject) {
571
680
  try {
572
681
  var full_query = search_query + " AND type:" + type;
573
682
  var query = that.SearchQuery.new(that.full_text_index || full_text_index, that.SearchQuery.queryString(full_query));
@@ -588,7 +697,7 @@ module.exports = class Database {
588
697
  that.cluster.query(query,
589
698
  /*#__PURE__*/
590
699
  function () {
591
- var _ref4 = _asyncToGenerator(function* (err, results, matrix) {
700
+ var _ref5 = _asyncToGenerator(function* (err, results, matrix) {
592
701
  var return_value = [];
593
702
 
594
703
  if (err) {
@@ -614,8 +723,8 @@ module.exports = class Database {
614
723
  }
615
724
  });
616
725
 
617
- return function (_x8, _x9, _x10) {
618
- return _ref4.apply(this, arguments);
726
+ return function (_x9, _x10, _x11) {
727
+ return _ref5.apply(this, arguments);
619
728
  };
620
729
  }());
621
730
  } catch (e) {
@@ -623,8 +732,8 @@ module.exports = class Database {
623
732
  }
624
733
  });
625
734
 
626
- return function (_x6, _x7) {
627
- return _ref3.apply(this, arguments);
735
+ return function (_x7, _x8) {
736
+ return _ref4.apply(this, arguments);
628
737
  };
629
738
  }());
630
739
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spice-couchbase",
3
- "version": "2.0.43",
3
+ "version": "2.0.45",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "axios": "^0.26.1",
13
- "couchbase": "^4.2.7",
13
+ "couchbase": "^4.6.0",
14
14
  "lodash": "^4.17.15",
15
15
  "qs": "^6.10.3"
16
16
  },
package/src/index.js CHANGED
@@ -24,6 +24,9 @@ if (!Promise.allSettled) {
24
24
  );
25
25
  }
26
26
 
27
+ // Couchbase lookupIn has a limit of 16 operations per call
28
+ const LOOKUP_IN_MAX_SPECS = 16;
29
+
27
30
  module.exports = class Database {
28
31
  constructor(
29
32
  connection,
@@ -265,13 +268,41 @@ module.exports = class Database {
265
268
  }
266
269
  }
267
270
 
268
- async get(doc_id) {
271
+ async get(doc_id, { columns = [] } = {}) {
269
272
  try {
270
- let response = await (
271
- this.use_bucket_name ? this.connection : this.collection
272
- ).get(doc_id);
273
+ const useLookupIn = columns.length > 0;
274
+ const collection = this.use_bucket_name ? this.connection : this.collection;
275
+
276
+ if (!useLookupIn) {
277
+ let response = await collection.get(doc_id);
278
+ return { id: doc_id, ...response.content };
279
+ }
280
+
281
+ // Batch columns into chunks of LOOKUP_IN_MAX_SPECS (16)
282
+ let value = { id: doc_id };
283
+ const columnBatches = _.chunk(columns, LOOKUP_IN_MAX_SPECS);
284
+
285
+ // Execute all batch requests in parallel
286
+ const batchPromises = columnBatches.map((batch) => {
287
+ const specs = batch.map((col) => couchbase.LookupInSpec.get(col));
288
+ return collection.lookupIn(doc_id, specs);
289
+ });
290
+
291
+ const batchResults = await Promise.allSettled(batchPromises);
292
+
293
+ // Merge results from all batches
294
+ batchResults.forEach((result, batchIndex) => {
295
+ if (result.status === "fulfilled" && result.value) {
296
+ const batch = columnBatches[batchIndex];
297
+ batch.forEach((col, colIndex) => {
298
+ if (result.value.content && result.value.content[colIndex]) {
299
+ value[col] = result.value.content[colIndex].value;
300
+ }
301
+ });
302
+ }
303
+ });
273
304
 
274
- return { id: doc_id, ...response.content };
305
+ return value;
275
306
  } catch (e) {
276
307
  console.error(e);
277
308
  }
@@ -302,8 +333,9 @@ module.exports = class Database {
302
333
 
303
334
  async count(doc_id, adjustment, initial_value) {
304
335
  let res = await (
305
- this.use_bucket_name ? this.connection : this.collection
306
- ).counter(doc_id, adjustment, {
336
+ this.use_bucket_name ?
337
+ this.connection
338
+ : this.collection).counter(doc_id, adjustment, {
307
339
  initial: initial_value,
308
340
  });
309
341
  return res.value;
@@ -311,8 +343,9 @@ module.exports = class Database {
311
343
 
312
344
  async update(doc_id, document, expiry) {
313
345
  let res = await (
314
- this.use_bucket_name ? this.connection : this.collection
315
- ).replace(doc_id, document, {
346
+ this.use_bucket_name ?
347
+ this.connection
348
+ : this.collection).replace(doc_id, document, {
316
349
  expiry: expiry,
317
350
  });
318
351
  return res.value;
@@ -320,38 +353,97 @@ module.exports = class Database {
320
353
 
321
354
  async delete(doc_id) {
322
355
  let res = await (
323
- this.use_bucket_name ? this.connection : this.collection
324
- ).remove(doc_id);
356
+ this.use_bucket_name ?
357
+ this.connection
358
+ : this.collection).remove(doc_id);
325
359
  return res.value;
326
360
  }
327
361
 
328
- async multi_get(keys, keep_type) {
362
+ async multi_get(keys, { keep_type = true, columns = [] } = {}) {
329
363
  if (keys.length == 0) {
330
364
  return [];
331
365
  }
332
366
  if (_.isArray(keys) && keys.length > 0) {
333
- let functions = _.map(keys, (key) =>
334
- (this.use_bucket_name ? this.connection : this.collection).get(key)
335
- );
336
- let returned_all = await Promise.allSettled(functions);
367
+ const useLookupIn = columns.length > 0;
368
+ const collection = this.use_bucket_name ? this.connection : this.collection;
337
369
 
338
- let responses = _.flatten(
339
- _.map(returned_all, (returned_obj) => {
340
- return returned_obj?.value;
341
- })
342
- );
370
+ if (!useLookupIn) {
371
+ // Regular get - no batching needed
372
+ let functions = _.map(keys, (key) => collection.get(key));
373
+ let returned_all = await Promise.allSettled(functions);
374
+
375
+ let responses = _.flatten(
376
+ _.map(returned_all, (returned_obj) => returned_obj?.value)
377
+ );
343
378
 
344
- return _.compact(
345
- _.map(responses, (res, index) => {
346
- if (res) {
347
- if (!keep_type) {
348
- delete res.value.type;
379
+ let final_responses = _.compact(
380
+ _.map(responses, (res, index) => {
381
+ if (res) {
382
+ let value = res.value;
383
+ if (!keep_type && value) {
384
+ delete value.type;
385
+ }
386
+ if (value) {
387
+ value.id = keys[index];
388
+ }
389
+ return value;
390
+ }
391
+ })
392
+ );
393
+
394
+ return final_responses;
395
+ }
396
+
397
+ // lookupIn with batching for columns > 16
398
+ const columnBatches = _.chunk(columns, LOOKUP_IN_MAX_SPECS);
399
+
400
+ // For each key, we need to fetch all column batches and merge the results
401
+ const keyPromises = _.map(keys, async (key) => {
402
+ try {
403
+ let value = { id: key };
404
+
405
+ // Execute all batch requests for this key in parallel
406
+ const batchPromises = columnBatches.map((batch) => {
407
+ const specs = batch.map((col) => couchbase.LookupInSpec.get(col));
408
+ return collection.lookupIn(key, specs);
409
+ });
410
+
411
+ const batchResults = await Promise.allSettled(batchPromises);
412
+
413
+ // Merge results from all batches
414
+ batchResults.forEach((result, batchIndex) => {
415
+ if (result.status === "fulfilled" && result.value) {
416
+ const batch = columnBatches[batchIndex];
417
+ batch.forEach((col, colIndex) => {
418
+ if (result.value.content && result.value.content[colIndex]) {
419
+ value[col] = result.value.content[colIndex].value;
420
+ }
421
+ });
349
422
  }
350
- res.value.id = keys[index];
351
- return res.value;
423
+ });
424
+
425
+ if (!keep_type && value) {
426
+ delete value.type;
352
427
  }
428
+
429
+ return value;
430
+ } catch (e) {
431
+ return null;
432
+ }
433
+ });
434
+
435
+ let results = await Promise.allSettled(keyPromises);
436
+ let final_responses = _.compact(
437
+ _.map(results, (result) => {
438
+ if (result.status === "fulfilled" && result.value) {
439
+ // Only return if we got at least some data beyond just the id
440
+ return Object.keys(result.value).length > 1 ? result.value : null;
441
+ }
442
+ return null;
353
443
  })
354
444
  );
445
+
446
+ return final_responses;
355
447
  } else {
356
448
  return [];
357
449
  }