|
1 | 1 | var |
| 2 | + KuzzleSearchResult = require('./kuzzleSearchResult'), |
2 | 3 | KuzzleDocument = require('./kuzzleDocument'), |
3 | 4 | KuzzleDataMapping = require('./kuzzleDataMapping'), |
4 | 5 | KuzzleRoom = require('./kuzzleRoom'), |
|
15 | 16 | /** |
16 | 17 | * A data collection is a set of data managed by Kuzzle. It acts like a data table for persistent documents, |
17 | 18 | * or like a room for pub/sub messages. |
| 19 | + * |
| 20 | + * @property {string} collection |
| 21 | + * @property {string} index |
| 22 | + * @property {Kuzzle} kuzzle |
| 23 | + * @property {Array.<string>} collection |
18 | 24 | * @param {object} kuzzle - Kuzzle instance to inherit from |
19 | 25 | * @param {string} collection - name of the data collection to handle |
20 | 26 | * @param {string} index - Index containing the data collection |
@@ -72,61 +78,6 @@ function KuzzleDataCollection(kuzzle, collection, index) { |
72 | 78 | return this; |
73 | 79 | } |
74 | 80 |
|
75 | | -/** |
76 | | - * Executes an advanced search on the data collection. |
77 | | - * |
78 | | - * /!\ There is a small delay between documents creation and their existence in our advanced search layer, |
79 | | - * usually a couple of seconds. |
80 | | - * That means that a document that was just been created won’t be returned by this function. |
81 | | - * |
82 | | - * @param {object} filters - Filters in Elasticsearch Query DSL format |
83 | | - * @param {object} [options] - Optional parameters |
84 | | - * @param {responseCallback} cb - Handles the query response |
85 | | - */ |
86 | | -KuzzleDataCollection.prototype.advancedSearch = function (filters, options, cb) { |
87 | | - var |
88 | | - query, |
89 | | - self = this; |
90 | | - |
91 | | - if (!cb && typeof options === 'function') { |
92 | | - cb = options; |
93 | | - options = null; |
94 | | - } |
95 | | - |
96 | | - self.kuzzle.callbackRequired('KuzzleDataCollection.advancedSearch', cb); |
97 | | - |
98 | | - query = self.kuzzle.addHeaders({body: filters}, this.headers); |
99 | | - |
100 | | - self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) { |
101 | | - var |
102 | | - response, |
103 | | - documents = []; |
104 | | - |
105 | | - if (error) { |
106 | | - return cb(error); |
107 | | - } |
108 | | - |
109 | | - result.result.hits.forEach(function (doc) { |
110 | | - var newDocument = new KuzzleDocument(self, doc._id, doc._source); |
111 | | - |
112 | | - newDocument.version = doc._version; |
113 | | - |
114 | | - documents.push(newDocument); |
115 | | - }); |
116 | | - |
117 | | - response = { |
118 | | - total: result.result.total, |
119 | | - documents: documents |
120 | | - }; |
121 | | - |
122 | | - if (result.result.aggregations) { |
123 | | - response.aggregations = result.result.aggregations; |
124 | | - } |
125 | | - |
126 | | - cb(null, response); |
127 | | - }); |
128 | | -}; |
129 | | - |
130 | 81 | /** |
131 | 82 | * Returns the number of documents matching the provided set of filters. |
132 | 83 | * |
@@ -332,16 +283,51 @@ KuzzleDataCollection.prototype.fetchDocument = function (documentId, options, cb |
332 | 283 | * @param {responseCallback} cb - Handles the query response |
333 | 284 | */ |
334 | 285 | KuzzleDataCollection.prototype.fetchAllDocuments = function (options, cb) { |
335 | | - var filters = {}; |
| 286 | + var |
| 287 | + warnEmitted = false, |
| 288 | + documents = [], |
| 289 | + filters = {}; |
336 | 290 |
|
337 | 291 | if (!cb && typeof options === 'function') { |
338 | 292 | cb = options; |
339 | | - options = null; |
| 293 | + options = {}; |
340 | 294 | } |
341 | 295 |
|
342 | | - this.kuzzle.callbackRequired('KuzzleDataCollection.fetchAll', cb); |
| 296 | + // copying pagination options to the search filter |
| 297 | + if (!options) { |
| 298 | + options = {}; |
| 299 | + } |
| 300 | + |
| 301 | + if (!options.from) { |
| 302 | + options.from = 0; |
| 303 | + } |
| 304 | + |
| 305 | + if (!options.size) { |
| 306 | + options.size = 1000; |
| 307 | + } |
| 308 | + |
| 309 | + this.kuzzle.callbackRequired('KuzzleDataCollection.fetchAllDocuments', cb); |
| 310 | + |
| 311 | + this.search(filters, options, function getNextDocuments (error, searchResult) { |
| 312 | + if (error) { |
| 313 | + return cb(error); |
| 314 | + } |
| 315 | + |
| 316 | + if (searchResult instanceof KuzzleSearchResult) { |
| 317 | + if (searchResult.total > 10000 && !warnEmitted) { |
| 318 | + warnEmitted = true; |
| 319 | + console.warn('KuzzleDataCollection.fetchAllDocuments may return extremely large amounts of documents, which may cause performance issues. Unless you know what you are doing, consider using KuzzleDataCollection.search or KuzzleDataCollection.scroll instead'); // eslint-disable-line no-console |
| 320 | + } |
343 | 321 |
|
344 | | - this.advancedSearch(filters, options, cb); |
| 322 | + searchResult.documents.forEach(document => { |
| 323 | + documents.push(document); |
| 324 | + }); |
| 325 | + searchResult.next(getNextDocuments); |
| 326 | + } |
| 327 | + else { |
| 328 | + cb(null, documents); |
| 329 | + } |
| 330 | + }); |
345 | 331 | }; |
346 | 332 |
|
347 | 333 |
|
@@ -435,6 +421,131 @@ KuzzleDataCollection.prototype.replaceDocument = function (documentId, content, |
435 | 421 | return this; |
436 | 422 | }; |
437 | 423 |
|
| 424 | +/** |
| 425 | + * Executes an advanced search on the data collection. |
| 426 | + * |
| 427 | + * /!\ There is a small delay between documents creation and their existence in our advanced search layer, |
| 428 | + * usually a couple of seconds. |
| 429 | + * That means that a document that was just been created won’t be returned by this function. |
| 430 | + * |
| 431 | + * @param {object} filters - Filters in Elasticsearch Query DSL format |
| 432 | + * @param {object} [options] - Optional parameters |
| 433 | + * @param {responseCallback} cb - Handles the query response |
| 434 | + */ |
| 435 | + |
| 436 | +KuzzleDataCollection.prototype.search = function (filters, options, cb) { |
| 437 | + var |
| 438 | + query, |
| 439 | + self = this; |
| 440 | + |
| 441 | + if (!cb && typeof options === 'function') { |
| 442 | + cb = options; |
| 443 | + options = {}; |
| 444 | + } |
| 445 | + |
| 446 | + self.kuzzle.callbackRequired('KuzzleDataCollection.search', cb); |
| 447 | + |
| 448 | + query = self.kuzzle.addHeaders({body: filters}, this.headers); |
| 449 | + |
| 450 | + |
| 451 | + self.kuzzle.query(this.buildQueryArgs('document', 'search'), query, options, function (error, result) { |
| 452 | + var documents = []; |
| 453 | + |
| 454 | + if (error) { |
| 455 | + return cb(error); |
| 456 | + } |
| 457 | + |
| 458 | + result.result.hits.forEach(function (doc) { |
| 459 | + var newDocument = new KuzzleDocument(self, doc._id, doc._source); |
| 460 | + |
| 461 | + newDocument.version = doc._version; |
| 462 | + |
| 463 | + documents.push(newDocument); |
| 464 | + }); |
| 465 | + |
| 466 | + if (result.result._scroll_id) { |
| 467 | + options.scrollId = result.result._scroll_id; |
| 468 | + } |
| 469 | + |
| 470 | + cb(null, new KuzzleSearchResult( |
| 471 | + self, |
| 472 | + result.result.total, |
| 473 | + documents, |
| 474 | + result.result.aggregations ? result.result.aggregations : [], |
| 475 | + {options: options, filters: filters} |
| 476 | + )); |
| 477 | + }); |
| 478 | +}; |
| 479 | + |
| 480 | +/** |
| 481 | + * A "scroll" option can be passed to search queries, creating persistent |
| 482 | + * paginated results. |
| 483 | + * This method can be used to manually get the next page of a search result, |
| 484 | + * instead of using KuzzleSearchResult.next() |
| 485 | + * |
| 486 | + * @param {string} scrollId |
| 487 | + * @param {object} [options] |
| 488 | + * @param {object} [filters] |
| 489 | + * @param {responseCallback} cb |
| 490 | + */ |
| 491 | +KuzzleDataCollection.prototype.scroll = function (scrollId, options, filters, cb) { |
| 492 | + var |
| 493 | + request = {body: {}}, |
| 494 | + self = this; |
| 495 | + |
| 496 | + if (!scrollId) { |
| 497 | + throw new Error('KuzzleDataCollection.scroll: scrollId required'); |
| 498 | + } |
| 499 | + |
| 500 | + if (!cb) { |
| 501 | + cb = filters; |
| 502 | + filters = null; |
| 503 | + } |
| 504 | + |
| 505 | + if (!cb && typeof options === 'function') { |
| 506 | + cb = options; |
| 507 | + options = {}; |
| 508 | + } |
| 509 | + |
| 510 | + if (!options) { |
| 511 | + options = {}; |
| 512 | + } |
| 513 | + |
| 514 | + options.scrollId = scrollId; |
| 515 | + |
| 516 | + this.kuzzle.callbackRequired('KuzzleDataCollection.scroll', cb); |
| 517 | + |
| 518 | + this.kuzzle.query({controller: 'document', action: 'scroll'}, request, options, function (error, result) { |
| 519 | + var documents = []; |
| 520 | + |
| 521 | + if (error) { |
| 522 | + return cb(error); |
| 523 | + } |
| 524 | + |
| 525 | + result.result.hits.forEach(function (doc) { |
| 526 | + var newDocument = new KuzzleDocument(self, doc._id, doc._source); |
| 527 | + |
| 528 | + newDocument.version = doc._version; |
| 529 | + |
| 530 | + documents.push(newDocument); |
| 531 | + }); |
| 532 | + |
| 533 | + if (result.result._scroll_id) { |
| 534 | + options.scrollId = result.result._scroll_id; |
| 535 | + } |
| 536 | + |
| 537 | + cb(null, new KuzzleSearchResult( |
| 538 | + self, |
| 539 | + result.result.total, |
| 540 | + documents, |
| 541 | + result.result.aggregations ? result.result.aggregations : [], |
| 542 | + {options: options, filters: filters} |
| 543 | + )); |
| 544 | + }); |
| 545 | + |
| 546 | + return this; |
| 547 | +}; |
| 548 | + |
438 | 549 | /** |
439 | 550 | * Subscribes to this data collection with a set of filters. |
440 | 551 | * To subscribe to the entire data collection, simply provide an empty filter. |
|
0 commit comments