@toxplanet/pegasus-sdk 1.1.6 → 1.1.8
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/config/environment.acc.js +1 -1
- package/config/environment.dev.js +5 -5
- package/config/environment.qa.js +1 -1
- package/lib/chemicals.js +169 -106
- package/lib/connection.js +5 -1
- package/lib/db/index.js +18 -11
- package/lib/elasticsearch.js +13 -8
- package/package.json +1 -1
|
@@ -19,9 +19,9 @@ module.exports = {
|
|
|
19
19
|
rejectUnauthorized: false
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
|
-
indexRoutes: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
22
|
+
indexRoutes: {
|
|
23
|
+
chemicals: ['chemicals*'],
|
|
24
|
+
documents: ['documents*'],
|
|
25
|
+
search: [/^(chemicals|substances|search)/]
|
|
26
|
+
}
|
|
27
27
|
};
|
package/config/environment.qa.js
CHANGED
package/lib/chemicals.js
CHANGED
|
@@ -628,121 +628,171 @@ class ChemicalsService {
|
|
|
628
628
|
}
|
|
629
629
|
}
|
|
630
630
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
index: async (params) => {
|
|
637
|
-
const chemical = params.body;
|
|
638
|
-
const result = await this.createChemical(chemical);
|
|
639
|
-
|
|
640
|
-
return {
|
|
641
|
-
_index: params.index,
|
|
642
|
-
_id: result.chemicalId,
|
|
643
|
-
_version: 1,
|
|
644
|
-
result: 'created',
|
|
645
|
-
_source: result
|
|
646
|
-
};
|
|
647
|
-
},
|
|
631
|
+
_buildEsHandlers() {
|
|
632
|
+
return {
|
|
633
|
+
index: async (params) => {
|
|
634
|
+
const chemical = params.body;
|
|
635
|
+
const result = await this.createChemical(chemical);
|
|
648
636
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
637
|
+
return {
|
|
638
|
+
_index: params.index,
|
|
639
|
+
_id: result.chemicalId,
|
|
640
|
+
_version: 1,
|
|
641
|
+
result: 'created',
|
|
642
|
+
_source: result
|
|
643
|
+
};
|
|
644
|
+
},
|
|
645
|
+
|
|
646
|
+
bulk: async (params) => {
|
|
647
|
+
const operations = params.body || params.operations;
|
|
648
|
+
const cdiDocuments = [];
|
|
649
|
+
|
|
650
|
+
for (let i = 0; i < operations.length; i++) {
|
|
651
|
+
const op = operations[i];
|
|
652
|
+
if ((op.index || op.create) &&
|
|
653
|
+
(op.index?._index === 'chemical_data_index' || op.create?._index === 'chemical_data_index')) {
|
|
654
|
+
const doc = operations[i + 1];
|
|
655
|
+
const sourceId = op.index?._id || op.create?._id;
|
|
656
|
+
if (doc && sourceId) {
|
|
657
|
+
cdiDocuments.push({
|
|
658
|
+
source_id: sourceId,
|
|
659
|
+
chemical_name: doc.chemical_primary_name || (doc.chemical_names && doc.chemical_names[0]) || null,
|
|
660
|
+
chemical_meta: doc.chemical_meta || {},
|
|
661
|
+
chemical_identifiers: doc.chemical_identifiers || {},
|
|
662
|
+
chemical_synonyms: doc.chemical_synonyms || [],
|
|
663
|
+
chemical_categories: doc.chemical_categories || [],
|
|
664
|
+
created_at: doc.chemical_created_at,
|
|
665
|
+
updated_at: doc.chemical_updated_at
|
|
666
|
+
});
|
|
667
|
+
i++;
|
|
659
668
|
}
|
|
660
669
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
status: 400,
|
|
680
|
-
error: {
|
|
681
|
-
type: 'mapper_parsing_exception',
|
|
682
|
-
reason: res.error
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
if (cdiDocuments.length === 0) {
|
|
673
|
+
return { took: 0, errors: false, items: [] };
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const result = await this.bulkIndexFielded(cdiDocuments);
|
|
677
|
+
|
|
678
|
+
return {
|
|
679
|
+
took: 1,
|
|
680
|
+
errors: result.errors.length > 0,
|
|
681
|
+
items: result.results.map((res, idx) => ({
|
|
682
|
+
index: {
|
|
683
|
+
_index: 'chemical_data_index',
|
|
684
|
+
_id: cdiDocuments[idx].source_id,
|
|
685
|
+
status: res.success ? 200 : 400,
|
|
686
|
+
result: res.success ? 'created' : 'error',
|
|
687
|
+
...(res.success ? {} : { error: { type: 'mapper_parsing_exception', reason: res.error } })
|
|
686
688
|
}
|
|
687
|
-
})
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
};
|
|
694
|
-
},
|
|
695
|
-
|
|
696
|
-
get: async (params) => {
|
|
697
|
-
const result = await this.getChemicalById(params.id);
|
|
698
|
-
|
|
699
|
-
if (!result) {
|
|
700
|
-
return {
|
|
701
|
-
_index: params.index,
|
|
702
|
-
_id: params.id,
|
|
703
|
-
found: false
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return {
|
|
708
|
-
_index: params.index,
|
|
709
|
-
_id: result.chemicalId,
|
|
710
|
-
_version: 1,
|
|
711
|
-
found: true,
|
|
712
|
-
_source: result
|
|
713
|
-
};
|
|
714
|
-
},
|
|
689
|
+
}))
|
|
690
|
+
};
|
|
691
|
+
},
|
|
692
|
+
|
|
693
|
+
get: async (params) => {
|
|
694
|
+
const result = await this.getChemicalBySourceId(params.id);
|
|
715
695
|
|
|
716
|
-
|
|
717
|
-
const result = await this.updateChemical(params.id, params.body);
|
|
718
|
-
|
|
696
|
+
if (!result) {
|
|
719
697
|
return {
|
|
720
698
|
_index: params.index,
|
|
721
699
|
_id: params.id,
|
|
722
|
-
|
|
723
|
-
result: result ? 'updated' : 'noop',
|
|
724
|
-
_source: result
|
|
700
|
+
found: false
|
|
725
701
|
};
|
|
726
|
-
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return {
|
|
705
|
+
_index: params.index,
|
|
706
|
+
_id: params.id,
|
|
707
|
+
_version: 1,
|
|
708
|
+
found: true,
|
|
709
|
+
_source: result
|
|
710
|
+
};
|
|
711
|
+
},
|
|
712
|
+
|
|
713
|
+
update: async (params) => {
|
|
714
|
+
const result = await this.updateChemical(params.id, params.body);
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
_index: params.index,
|
|
718
|
+
_id: params.id,
|
|
719
|
+
_version: 2,
|
|
720
|
+
result: result ? 'updated' : 'noop',
|
|
721
|
+
_source: result
|
|
722
|
+
};
|
|
723
|
+
},
|
|
724
|
+
|
|
725
|
+
delete: async (params) => {
|
|
726
|
+
if (params.index === 'synonym_lookup_index') {
|
|
727
|
+
return { _index: params.index, _id: params.id, result: 'not_found' };
|
|
728
|
+
}
|
|
729
|
+
const result = await this.deleteBySourceId(params.id);
|
|
730
|
+
|
|
731
|
+
return {
|
|
732
|
+
_index: params.index,
|
|
733
|
+
_id: params.id,
|
|
734
|
+
result: result ? 'deleted' : 'not_found'
|
|
735
|
+
};
|
|
736
|
+
},
|
|
737
|
+
|
|
738
|
+
deleteByQuery: async (params) => {
|
|
739
|
+
const sourceId = params.body?.query?.term?.chemical_set_identifier
|
|
740
|
+
|| params.body?.query?.term?.source_id;
|
|
741
|
+
if (!sourceId) {
|
|
742
|
+
return { deleted: 0, failures: [] };
|
|
743
|
+
}
|
|
744
|
+
const result = await this.deleteBySourceId(sourceId);
|
|
745
|
+
return {
|
|
746
|
+
deleted: result ? 1 : 0,
|
|
747
|
+
failures: []
|
|
748
|
+
};
|
|
749
|
+
},
|
|
750
|
+
|
|
751
|
+
search: async (params) => {
|
|
752
|
+
let searchTerm = '';
|
|
753
|
+
let limit = params.body?.size || 10;
|
|
727
754
|
|
|
728
|
-
|
|
729
|
-
const
|
|
755
|
+
if (params.index === 'synonym_lookup_index') {
|
|
756
|
+
const query = params.body?.query;
|
|
757
|
+
searchTerm = query?.match?.chemical_name ||
|
|
758
|
+
query?.term?.chemical_name ||
|
|
759
|
+
query?.query_string?.query || '';
|
|
760
|
+
const searchResults = await this.searchBySynonym(searchTerm, limit);
|
|
730
761
|
|
|
731
762
|
return {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
763
|
+
took: 1,
|
|
764
|
+
timed_out: false,
|
|
765
|
+
_shards: {
|
|
766
|
+
total: 1,
|
|
767
|
+
successful: 1,
|
|
768
|
+
skipped: 0,
|
|
769
|
+
failed: 0
|
|
770
|
+
},
|
|
771
|
+
hits: {
|
|
772
|
+
total: {
|
|
773
|
+
value: searchResults.results.length,
|
|
774
|
+
relation: 'eq'
|
|
775
|
+
},
|
|
776
|
+
max_score: searchResults.results[0]?.score || 0,
|
|
777
|
+
hits: searchResults.results.map(result => ({
|
|
778
|
+
_index: params.index,
|
|
779
|
+
_id: result.id,
|
|
780
|
+
_score: result.score,
|
|
781
|
+
_source: {
|
|
782
|
+
postgres_id: result.id,
|
|
783
|
+
chemical_name: result.name,
|
|
784
|
+
cas_numbers: result.cas,
|
|
785
|
+
identifier_values: result.identifiers,
|
|
786
|
+
synonyms: result.synonyms
|
|
787
|
+
}
|
|
788
|
+
}))
|
|
789
|
+
}
|
|
736
790
|
};
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
search: async (params) => {
|
|
791
|
+
} else {
|
|
740
792
|
const query = params.body?.query;
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
const limit = params.body?.size || 10;
|
|
745
|
-
|
|
793
|
+
searchTerm = query?.match?.chemical_name ||
|
|
794
|
+
query?.term?.chemical_name ||
|
|
795
|
+
query?.query_string?.query || '';
|
|
746
796
|
const searchResults = await this.searchByName(searchTerm, limit);
|
|
747
797
|
|
|
748
798
|
return {
|
|
@@ -774,12 +824,25 @@ class ChemicalsService {
|
|
|
774
824
|
}))
|
|
775
825
|
}
|
|
776
826
|
};
|
|
777
|
-
},
|
|
778
|
-
|
|
779
|
-
count: async (params) => {
|
|
780
|
-
return await this.countAll();
|
|
781
827
|
}
|
|
782
|
-
}
|
|
828
|
+
},
|
|
829
|
+
|
|
830
|
+
count: async (params) => {
|
|
831
|
+
if (params.index === 'synonym_lookup_index') {
|
|
832
|
+
return await this.getTotalSynonymCount();
|
|
833
|
+
}
|
|
834
|
+
return await this.countAll();
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
registerElasticsearchHandlers(elasticsearchService) {
|
|
840
|
+
const configurablePatterns = this.connection.config.indexRoutes?.chemicals || ['chemicals*'];
|
|
841
|
+
const legacyPatterns = ['synonym_lookup_index', 'chemical_data_index', 'chemical_converter_index'];
|
|
842
|
+
const allPatterns = [...new Set([...configurablePatterns, ...legacyPatterns])];
|
|
843
|
+
const handlers = this._buildEsHandlers();
|
|
844
|
+
allPatterns.forEach(pattern => {
|
|
845
|
+
elasticsearchService.registerIndexRoute(pattern, handlers);
|
|
783
846
|
});
|
|
784
847
|
}
|
|
785
848
|
}
|
package/lib/connection.js
CHANGED
|
@@ -195,7 +195,11 @@ class PegasusConnection {
|
|
|
195
195
|
|
|
196
196
|
async query(sql, params) {
|
|
197
197
|
const pool = this.getPostgresClient();
|
|
198
|
-
|
|
198
|
+
const start = Date.now();
|
|
199
|
+
logInfo('pegasus-sdk', `[SQL] ${sql}${params ? ` -- params: ${JSON.stringify(params)}` : ''}`);
|
|
200
|
+
const result = await pool.query(sql, params);
|
|
201
|
+
logInfo('pegasus-sdk', `[SQL] rowCount: ${result.rowCount} duration: ${Date.now() - start}ms`);
|
|
202
|
+
return result;
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
async getClient() {
|
package/lib/db/index.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
const { drizzle } = require('drizzle-orm/node-postgres');
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
const { drizzle } = require('drizzle-orm/node-postgres');
|
|
2
|
+
const { logInfo } = require('@toxplanet/tphelper/logging');
|
|
3
|
+
const schema = require('./schema');
|
|
4
|
+
|
|
5
|
+
const logger = {
|
|
6
|
+
logQuery(query, params) {
|
|
7
|
+
logInfo('pegasus-sdk', `[SQL] ${query}${params?.length ? ` -- params: ${JSON.stringify(params)}` : ''}`);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function getDrizzle(pgPool) {
|
|
12
|
+
return drizzle(pgPool, { schema, logger });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = {
|
|
16
|
+
getDrizzle,
|
|
17
|
+
schema
|
|
18
|
+
};
|
package/lib/elasticsearch.js
CHANGED
|
@@ -69,17 +69,22 @@ class ElasticsearchService {
|
|
|
69
69
|
throw new Error('Bulk operations must be a non-empty array');
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
let indexName = params.index;
|
|
73
|
+
let cdiIndexName = null;
|
|
74
|
+
for (const op of operations) {
|
|
75
|
+
const name = op?.index?._index || op?.index?.index ||
|
|
76
|
+
op?.create?._index || op?.create?.index ||
|
|
77
|
+
op?.delete?._index || op?.delete?.index ||
|
|
78
|
+
op?.update?._index || op?.update?.index;
|
|
79
|
+
if (!name) continue;
|
|
80
|
+
if (name === 'chemical_data_index') { cdiIndexName = name; break; }
|
|
81
|
+
if (!indexName) indexName = name;
|
|
77
82
|
}
|
|
83
|
+
indexName = cdiIndexName || indexName;
|
|
84
|
+
if (!indexName) throw new Error('Could not determine index from bulk operations');
|
|
78
85
|
|
|
79
86
|
const handler = this.getRouteHandler(indexName);
|
|
80
|
-
if (handler && handler.bulk)
|
|
81
|
-
return await handler.bulk(params);
|
|
82
|
-
}
|
|
87
|
+
if (handler && handler.bulk) return await handler.bulk(params);
|
|
83
88
|
throw new Error(`No handler registered for index: ${indexName}`);
|
|
84
89
|
}
|
|
85
90
|
|
package/package.json
CHANGED