@cumulus/es-client 13.4.0 → 14.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/esDefaults.js +1 -1
- package/indexer.js +74 -16
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -8,6 +8,13 @@ Utilities for working with Elasticsearch.
|
|
|
8
8
|
npm install @cumulus/es-client
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Notes
|
|
12
|
+
|
|
13
|
+
### Sorting
|
|
14
|
+
|
|
15
|
+
It is possible to sort the Elastic Search results by specifying `sort_by`, `sort_key`, and `order` params.
|
|
16
|
+
If not provided, the default sorting will be applied (`{ timestamp: { order: 'desc' } }` as of this writing).
|
|
17
|
+
|
|
11
18
|
## About Cumulus
|
|
12
19
|
|
|
13
20
|
Cumulus is a cloud-based data ingest, archive, distribution and management prototype for NASA's
|
package/esDefaults.js
CHANGED
package/indexer.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
1
3
|
/* functions for transforming and indexing Cumulus Payloads
|
|
2
4
|
* in Elasticsearch. These functions are specifically designed
|
|
3
5
|
* to transform data for use in cumulus api
|
|
@@ -11,11 +13,13 @@
|
|
|
11
13
|
'use strict';
|
|
12
14
|
|
|
13
15
|
const cloneDeep = require('lodash/cloneDeep');
|
|
16
|
+
const isEqual = require('lodash/isEqual');
|
|
14
17
|
|
|
15
18
|
const Logger = require('@cumulus/logger');
|
|
16
19
|
const { inTestMode } = require('@cumulus/common/test-utils');
|
|
17
|
-
const { IndexExistsError } = require('@cumulus/errors');
|
|
20
|
+
const { IndexExistsError, ValidationError } = require('@cumulus/errors');
|
|
18
21
|
const { constructCollectionId } = require('@cumulus/message/Collections');
|
|
22
|
+
const { removeNilProperties } = require('@cumulus/common/util');
|
|
19
23
|
|
|
20
24
|
const { Search, defaultIndexAlias } = require('./search');
|
|
21
25
|
const mappings = require('./config/mappings.json');
|
|
@@ -284,15 +288,27 @@ async function indexGranule(esClient, payload, index = defaultIndexAlias, type =
|
|
|
284
288
|
);
|
|
285
289
|
}
|
|
286
290
|
|
|
291
|
+
const granuleInvalidNullFields = [
|
|
292
|
+
'granuleId',
|
|
293
|
+
'collectionId',
|
|
294
|
+
'status',
|
|
295
|
+
'updatedAt',
|
|
296
|
+
'execution',
|
|
297
|
+
'createdAt',
|
|
298
|
+
];
|
|
299
|
+
|
|
287
300
|
/**
|
|
288
301
|
* Upserts a granule in Elasticsearch
|
|
289
302
|
*
|
|
290
303
|
* @param {Object} params
|
|
291
|
-
* @param {Object} params.esClient
|
|
292
|
-
* @param {Object} params.updates
|
|
293
|
-
* @param {string} params.index
|
|
294
|
-
*
|
|
295
|
-
* @param {string} [params.
|
|
304
|
+
* @param {Object} params.esClient - Elasticsearch Connection object
|
|
305
|
+
* @param {Object} params.updates - Updates to make
|
|
306
|
+
* @param {string | undefined} params.index - Elasticsearch index alias
|
|
307
|
+
* (default defined in search.js)
|
|
308
|
+
* @param {string} [params.type] - Elasticsearch type (default: granule)
|
|
309
|
+
* @param {string} [params.refresh] - whether to refresh the index on update or not
|
|
310
|
+
* @param {boolean} writeConstraints - boolean toggle restricting if conditionals should
|
|
311
|
+
* be used to determine write eligibility
|
|
296
312
|
* @returns {Promise} Elasticsearch response
|
|
297
313
|
*/
|
|
298
314
|
async function upsertGranule({
|
|
@@ -301,7 +317,12 @@ async function upsertGranule({
|
|
|
301
317
|
index = defaultIndexAlias,
|
|
302
318
|
type = 'granule',
|
|
303
319
|
refresh,
|
|
304
|
-
}) {
|
|
320
|
+
}, writeConstraints = true) {
|
|
321
|
+
Object.keys(updates).forEach((key) => {
|
|
322
|
+
if (updates[key] === null && granuleInvalidNullFields.includes(key)) {
|
|
323
|
+
throw new ValidationError(`Attempted DynamoDb write with invalid key ${key} set to null. Please remove or change this field and retry`);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
305
326
|
// If the granule exists in 'deletedgranule', delete it first before inserting the granule
|
|
306
327
|
// into ES. Ignore 404 error, so the deletion still succeeds if the record doesn't exist.
|
|
307
328
|
const delGranParams = {
|
|
@@ -313,7 +334,50 @@ async function upsertGranule({
|
|
|
313
334
|
};
|
|
314
335
|
await esClient.delete(delGranParams, { ignore: [404] });
|
|
315
336
|
|
|
316
|
-
|
|
337
|
+
// Remove nils in case there isn't a collision
|
|
338
|
+
const upsertDoc = removeNilProperties(updates);
|
|
339
|
+
let removeString = '';
|
|
340
|
+
|
|
341
|
+
// Set field removal for null values
|
|
342
|
+
Object.entries(updates).forEach(([fieldName, value]) => {
|
|
343
|
+
// File removal is a special case as null gets set to []
|
|
344
|
+
if (fieldName === 'files' && isEqual(value, [])) {
|
|
345
|
+
removeString += `ctx._source.remove('${fieldName}'); `;
|
|
346
|
+
delete upsertDoc.files; // Remove files in case this is not a scripted upsert
|
|
347
|
+
}
|
|
348
|
+
if (value === null) {
|
|
349
|
+
removeString += `ctx._source.remove('${fieldName}'); `;
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
let inlineDocWriteString = 'ctx._source.putAll(params.doc);';
|
|
354
|
+
if (removeString !== '') {
|
|
355
|
+
inlineDocWriteString += removeString;
|
|
356
|
+
}
|
|
357
|
+
let inline = inlineDocWriteString;
|
|
358
|
+
|
|
359
|
+
if (writeConstraints === true) {
|
|
360
|
+
// Because both API write and message write chains use the granule model to store records, in
|
|
361
|
+
// cases where createdAt does not exist on the granule, we assume overwrite protections are
|
|
362
|
+
// undesired behavior via business logic on the message write logic
|
|
363
|
+
inline = `
|
|
364
|
+
if ((ctx._source.createdAt === null || params.doc.createdAt >= ctx._source.createdAt)
|
|
365
|
+
&& ((params.doc.status != 'running' && params.doc.status != 'queued') || ((params.doc.status == 'running' || params.doc.status == 'queued') && params.doc.execution != ctx._source.execution))) {
|
|
366
|
+
${inlineDocWriteString}
|
|
367
|
+
} else {
|
|
368
|
+
ctx.op = 'none';
|
|
369
|
+
}
|
|
370
|
+
`;
|
|
371
|
+
if (!updates.createdAt) {
|
|
372
|
+
inline = `
|
|
373
|
+
if ((params.doc.status != 'running' && params.doc.status != 'queued') || ((params.doc.status == 'running' || params.doc.status == 'queued') && params.doc.execution != ctx._source.execution)) {
|
|
374
|
+
${inlineDocWriteString}
|
|
375
|
+
} else {
|
|
376
|
+
ctx.op = 'none';
|
|
377
|
+
}
|
|
378
|
+
`;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
317
381
|
|
|
318
382
|
return await esClient.update({
|
|
319
383
|
index,
|
|
@@ -323,14 +387,7 @@ async function upsertGranule({
|
|
|
323
387
|
body: {
|
|
324
388
|
script: {
|
|
325
389
|
lang: 'painless',
|
|
326
|
-
inline
|
|
327
|
-
if ((ctx._source.createdAt === null || params.doc.createdAt >= ctx._source.createdAt)
|
|
328
|
-
&& (params.doc.status != 'running' || (params.doc.status == 'running' && params.doc.execution != ctx._source.execution))) {
|
|
329
|
-
ctx._source.putAll(params.doc);
|
|
330
|
-
} else {
|
|
331
|
-
ctx.op = 'none';
|
|
332
|
-
}
|
|
333
|
-
`,
|
|
390
|
+
inline,
|
|
334
391
|
params: {
|
|
335
392
|
doc: upsertDoc,
|
|
336
393
|
},
|
|
@@ -709,4 +766,5 @@ module.exports = {
|
|
|
709
766
|
deleteGranule,
|
|
710
767
|
deleteExecution,
|
|
711
768
|
deleteReconciliationReport,
|
|
769
|
+
granuleInvalidNullFields,
|
|
712
770
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cumulus/es-client",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.1.0",
|
|
4
4
|
"description": "Utilities for working with Elasticsearch",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CUMULUS",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"author": "Cumulus Authors",
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@cumulus/common": "
|
|
34
|
-
"@cumulus/errors": "
|
|
35
|
-
"@cumulus/logger": "
|
|
36
|
-
"@cumulus/message": "
|
|
33
|
+
"@cumulus/common": "14.1.0",
|
|
34
|
+
"@cumulus/errors": "14.1.0",
|
|
35
|
+
"@cumulus/logger": "14.1.0",
|
|
36
|
+
"@cumulus/message": "14.1.0",
|
|
37
37
|
"@elastic/elasticsearch": "^5.6.20",
|
|
38
38
|
"aws-elasticsearch-connector": "8.2.0",
|
|
39
39
|
"aws-sdk": "^2.585.0",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"p-limit": "^1.2.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@cumulus/aws-client": "
|
|
46
|
-
"@cumulus/test-data": "
|
|
45
|
+
"@cumulus/aws-client": "14.1.0",
|
|
46
|
+
"@cumulus/test-data": "14.1.0",
|
|
47
47
|
"p-each-series": "^2.1.0"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "d97b5b37913944c0f0ecf958f2a567ec3714816c"
|
|
50
50
|
}
|