From 12d09e292f2a43bfb050cbba5feef1407b374360 Mon Sep 17 00:00:00 2001 From: Yoann Abbes Date: Thu, 11 Jun 2020 07:23:55 +0200 Subject: [PATCH 1/3] Add bulk:deleteByQuery --- .../controllers/bulk/delete-by-query/index.md | 43 +++++++++++++++++++ .../snippets/delete-by-query.js | 15 +++++++ .../snippets/delete-by-query.test.yml | 20 +++++++++ src/controllers/Bulk.js | 24 +++++++++++ src/protocols/routes.json | 4 ++ test/controllers/bulk.test.js | 21 +++++++++ 6 files changed, 127 insertions(+) create mode 100644 doc/7/controllers/bulk/delete-by-query/index.md create mode 100644 doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js create mode 100644 doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml diff --git a/doc/7/controllers/bulk/delete-by-query/index.md b/doc/7/controllers/bulk/delete-by-query/index.md new file mode 100644 index 000000000..cb1d77a62 --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/index.md @@ -0,0 +1,43 @@ +--- +code: true +type: page +title: deleteByQuery +--- + +# deleteByQuery + +Deletes documents matching the provided search query. + +This is a low level route intended to bypass Kuzzle actions on document deletion, notably: + - check document write limit + - trigger [realtime notifications](/core/2/guides/essentials/real-time) + +--- + +```js +deleteByQuery(index, collection, [query], [options]); +``` + +| Argument | Type | Description | +| ------------ | ----------------- | --------------- | +| `index` |
string
| Index name | +| `collection` |
string
| Collection name | +| `query` |
object
| documents matching this search query will be deleted. Uses the [ElasticSearch Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl.html) syntax. | +| `options` |
object
| Query options | + +### Options + +Additional query options + +| Options | Type
(default) | Description | +| ---------- | ------------------------------- | ---------------------------------------------------------------------------------- | +| `queuable` |
boolean

(`true`) | If true, queues the request during downtime, until connected to Kuzzle again | +| `refresh` |
string

(`""`) | If set to `wait_for`, waits for the change to be reflected for `search` (up to 1s) | + +## Resolves + +Resolves to a number of the deleted documents. + +## Usage + +<<< ./snippets/delete-by-query.js diff --git a/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js new file mode 100644 index 000000000..16cfba6ff --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js @@ -0,0 +1,15 @@ +try { + const deleted = await kuzzle.bulk.deleteByQuery( + 'nyc-open-data', + 'yellow-taxi', + { + query: { + term: { capacity: 7 } + } + } + ); + + console.log(`Successfully deleted ${deleted} documents`); +} catch (error) { + console.error(error.message); +} \ No newline at end of file diff --git a/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml new file mode 100644 index 000000000..f1a308132 --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml @@ -0,0 +1,20 @@ +name: bulk#deleteByQuery +description: Delete documents matching query +hooks: + before: | + curl -XDELETE kuzzle:7512/nyc-open-data + curl -XPOST kuzzle:7512/nyc-open-data/_create + curl -XPUT kuzzle:7512/nyc-open-data/yellow-taxi + + for i in 1 2 3 4 5; do + curl -H "Content-type: application/json" -d '{"capacity": 4}' kuzzle:7512/nyc-open-data/yellow-taxi/_create + done + + for i in 1 2 3 4 5; do + curl -H "Content-type: application/json" -d '{"capacity": 7}' kuzzle:7512/nyc-open-data/yellow-taxi/_create + done + + curl -XPOST kuzzle:7512/nyc-open-data/yellow-taxi/_refresh + after: +template: default +expected: Successfully deleted 5 documents diff --git a/src/controllers/Bulk.js b/src/controllers/Bulk.js index c11e36f4d..02e79d0f2 100644 --- a/src/controllers/Bulk.js +++ b/src/controllers/Bulk.js @@ -5,6 +5,30 @@ class BulkController extends BaseController { super(kuzzle, 'bulk'); } + /** + * Directly deletes every documents matching the search query without: + * - applying max documents write limit + * - fetching deleted documents + * - triggering realtime notifications + * {@link https://docs.kuzzle.io/core/2/api/controllers/bulk/delete-by-query/|Official documentation} + * @param {String} index - Index name + * @param {String} collection - Collection name + * @param {Object[]} query - Query matching documents to delete + * @param {Object} [options] - Additional options + * @returns {Promise} + */ + deleteByQuery(index, collection, query, options = {}) { + const request = { + index, + collection, + body: query, + action: 'deleteByQuery' + }; + + return this.query(request, options) + .then(response => response.result.deleted); + } + /** * Creates, updates or deletes large amounts of documents as fast as possible. * {@link https://docs.kuzzle.io/core/2/api/controllers/bulk/import/|Official documentation} diff --git a/src/protocols/routes.json b/src/protocols/routes.json index 1a6836f0d..df55cbad4 100644 --- a/src/protocols/routes.json +++ b/src/protocols/routes.json @@ -58,6 +58,10 @@ } }, "bulk": { + "deleteByQuery": { + "url": "/:index/:collection/_bulk/_query", + "verb": "DELETE" + }, "import": { "verb": "POST", "url": "/:index/:collection/_bulk" diff --git a/test/controllers/bulk.test.js b/test/controllers/bulk.test.js index 8df3e1e3f..750a6792a 100644 --- a/test/controllers/bulk.test.js +++ b/test/controllers/bulk.test.js @@ -20,6 +20,27 @@ describe('Bulk Controller', () => { kuzzle.bulk = new BulkController(kuzzle); }); + describe('deleteByQuery', () => { + it('should call document/deleteByQuery query and return a Promise which resolves the list of deleted document ids', () => { + kuzzle.query.resolves({ result: { deleted: 3 } }); + const options = {refresh: 'wait_for'}; + return kuzzle.bulk.deleteByQuery('index', 'collection', { query: { match: { foo: 'bar' } } }, options) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWith({ + controller: 'bulk', + action: 'deleteByQuery', + index: 'index', + collection: 'collection', + body: {query: {match: {foo: 'bar' }}} + }, options); + + should(res).be.an.Number(); + should(res).be.equal(3); + }); + }); + }); describe('import', () => { it('should call bulk/import query with the bulk data and return a Promise which resolves json object', () => { From 72016942f8ed28dfade9956bd7d7bf36d3a73f1b Mon Sep 17 00:00:00 2001 From: Yoann Abbes Date: Thu, 11 Jun 2020 07:29:35 +0200 Subject: [PATCH 2/3] default query --- src/controllers/Bulk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/Bulk.js b/src/controllers/Bulk.js index 02e79d0f2..2c48f1ce9 100644 --- a/src/controllers/Bulk.js +++ b/src/controllers/Bulk.js @@ -17,7 +17,7 @@ class BulkController extends BaseController { * @param {Object} [options] - Additional options * @returns {Promise} */ - deleteByQuery(index, collection, query, options = {}) { + deleteByQuery(index, collection, query = {}, options = {}) { const request = { index, collection, From adf324a1b30033f5ef9d2ee66b84ee2ec5646f21 Mon Sep 17 00:00:00 2001 From: Yoann-Abbes <44844010+Yoann-Abbes@users.noreply.github.com> Date: Thu, 11 Jun 2020 09:50:06 +0200 Subject: [PATCH 3/3] Update doc/7/controllers/bulk/delete-by-query/index.md Co-authored-by: Adrien Maret --- doc/7/controllers/bulk/delete-by-query/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/7/controllers/bulk/delete-by-query/index.md b/doc/7/controllers/bulk/delete-by-query/index.md index cb1d77a62..8a44b45a3 100644 --- a/doc/7/controllers/bulk/delete-by-query/index.md +++ b/doc/7/controllers/bulk/delete-by-query/index.md @@ -36,7 +36,7 @@ Additional query options ## Resolves -Resolves to a number of the deleted documents. +Resolves to the number of the deleted documents. ## Usage