@tekkare/romulus 0.1.251 → 0.1.253
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/dist/module.json +1 -1
- package/dist/runtime/utils/projects.d.ts +8 -0
- package/dist/runtime/utils/projects.js +8 -5
- package/layer/app/app.config.ts +6 -0
- package/layer/app/components/OipPubmedSummary.vue +223 -0
- package/layer/app/components/OipResourceDrawer.vue +331 -0
- package/layer/app/components/OipResourceDrawerLink.vue +40 -0
- package/layer/app/components/OipResourceField.vue +41 -0
- package/layer/app/components/OipResourceGenericCard.vue +54 -0
- package/layer/app/components/OipResourceSource.vue +50 -0
- package/layer/app/components/OipResourceTags.vue +65 -0
- package/layer/app/components/OipResourceView.vue +107 -0
- package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
- package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
- package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
- package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
- package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
- package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
- package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
- package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
- package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
- package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
- package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
- package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
- package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
- package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
- package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
- package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
- package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
- package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
- package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
- package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
- package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
- package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
- package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
- package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
- package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
- package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
- package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
- package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
- package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
- package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
- package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
- package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
- package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
- package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
- package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
- package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
- package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
- package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
- package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
- package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
- package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
- package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
- package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
- package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
- package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
- package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
- package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
- package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
- package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
- package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
- package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
- package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
- package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
- package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
- package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
- package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
- package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
- package/layer/app/components/oip-science/common/Form.vue +73 -0
- package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
- package/layer/app/components/oip-science/common/NoData.vue +16 -0
- package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
- package/layer/app/components/oip-science/common/Source.vue +31 -0
- package/layer/app/components/oip-science/common/TableTags.vue +279 -0
- package/layer/app/components/oip-science/common/Timeline.vue +104 -0
- package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
- package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
- package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
- package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
- package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
- package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
- package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
- package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
- package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
- package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
- package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
- package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
- package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
- package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
- package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
- package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
- package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
- package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
- package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
- package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
- package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
- package/layer/app/components/oip-science/euct/Locations.vue +102 -0
- package/layer/app/components/oip-science/euct/Products.vue +101 -0
- package/layer/app/components/oip-science/euct/Publications.vue +89 -0
- package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
- package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
- package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
- package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
- package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
- package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
- package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
- package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
- package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
- package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
- package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
- package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
- package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
- package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
- package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
- package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
- package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
- package/layer/app/composables/useOipChapterScroll.ts +43 -0
- package/layer/app/composables/useOipResourceHooks.ts +27 -0
- package/layer/app/composables/useOipResourceNav.ts +66 -0
- package/layer/app/composables/useOipResourceViews.ts +117 -0
- package/layer/app/composables/useOipResources.ts +83 -0
- package/layer/app/oip-drugs/PORTING.md +120 -0
- package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
- package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
- package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
- package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
- package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
- package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
- package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
- package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
- package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
- package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
- package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
- package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
- package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
- package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
- package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
- package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
- package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
- package/layer/app/oip-drugs/drugs.css +500 -0
- package/layer/app/oip-drugs/esIndices.ts +322 -0
- package/layer/app/oip-drugs/kinds.ts +264 -0
- package/layer/app/oip-drugs/locales/en.json +1571 -0
- package/layer/app/oip-drugs/locales/fr.json +1571 -0
- package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
- package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
- package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
- package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
- package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
- package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
- package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
- package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
- package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
- package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
- package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
- package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
- package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
- package/layer/app/oip-drugs/types/elastic.ts +113 -0
- package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
- package/layer/app/oip-drugs/types/es/directory.ts +54 -0
- package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
- package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
- package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
- package/layer/app/oip-drugs/types/es/portal.ts +130 -0
- package/layer/app/oip-drugs/types/es/retail.ts +107 -0
- package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
- package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
- package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
- package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
- package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
- package/layer/app/oip-drugs/utils/contributions.ts +36 -0
- package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
- package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
- package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
- package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
- package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
- package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
- package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
- package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
- package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
- package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
- package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
- package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
- package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
- package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
- package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
- package/layer/app/oip-science/PORTING.md +93 -0
- package/layer/app/oip-science/assets/smartSelection.json +428 -0
- package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
- package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
- package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
- package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
- package/layer/app/oip-science/composables/useEuct.ts +418 -0
- package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
- package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
- package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
- package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
- package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
- package/layer/app/oip-science/composables/usePubmed.ts +487 -0
- package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
- package/layer/app/oip-science/indexConfig.json +794 -0
- package/layer/app/oip-science/locales/en.json +483 -0
- package/layer/app/oip-science/locales/fr.json +483 -0
- package/layer/app/oip-science/science.css +1182 -0
- package/layer/app/oip-science/utils/a-openCard.ts +23 -0
- package/layer/app/oip-science/utils/b-openCard.ts +35 -0
- package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
- package/layer/app/oip-science/utils/f-types.ts +241 -0
- package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
- package/layer/app/oip-science/utils/matchMethod.ts +53 -0
- package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
- package/layer/app/oip-science/utils/sources.ts +15 -0
- package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
- package/layer/app/oip-science/utils/toPresets.ts +7 -0
- package/layer/app/oip-science/utils/valueTable.ts +126 -0
- package/layer/app/plugins/oip-science-i18n.ts +17 -0
- package/layer/app/utils/oipFicheRoutes.ts +118 -0
- package/layer/app/utils/oipResources.ts +440 -0
- package/layer/nuxt.config.ts +22 -2
- package/layer/public/reports/blincyto-has.html +292 -0
- package/layer/public/reports/blincyto-has.pdf +0 -0
- package/layer/public/reports/darzalex-has.html +279 -0
- package/layer/public/reports/darzalex-has.pdf +0 -0
- package/layer/public/reports/dupixent-has.html +217 -0
- package/layer/public/reports/dupixent-has.pdf +0 -0
- package/layer/public/reports/enhertu-has.html +283 -0
- package/layer/public/reports/enhertu-has.pdf +0 -0
- package/layer/public/reports/has-sein-2023.html +1639 -0
- package/layer/public/reports/ibrance-has.html +280 -0
- package/layer/public/reports/ibrance-has.pdf +0 -0
- package/layer/public/reports/imfinzi-has.html +297 -0
- package/layer/public/reports/imfinzi-has.pdf +0 -0
- package/layer/public/reports/keytruda-has.html +337 -0
- package/layer/public/reports/keytruda-has.pdf +0 -0
- package/layer/public/reports/kisqali-has.html +202 -0
- package/layer/public/reports/kisqali-has.pdf +0 -0
- package/layer/public/reports/opdivo-has.html +232 -0
- package/layer/public/reports/opdivo-has.pdf +0 -0
- package/layer/public/reports/ozempic-has.html +188 -0
- package/layer/public/reports/ozempic-has.pdf +0 -0
- package/layer/public/reports/tecentriq-has.html +315 -0
- package/layer/public/reports/tecentriq-has.pdf +0 -0
- package/layer/public/reports/yescarta-has.html +275 -0
- package/layer/public/reports/yescarta-has.pdf +0 -0
- package/layer/server/api/oip/es.post.ts +99 -0
- package/layer/server/api/oip/pdf.get.ts +70 -0
- package/layer/server/api/oip/reports.get.ts +98 -0
- package/layer/server/api/oip/resource-types.get.ts +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
// Portage de useElastic de France Augmented Science, pour les fiches du layer
|
|
2
|
+
// (cf. components/oip-science) : memes signatures, mais les requetes passent
|
|
3
|
+
// par le proxy du layer (/api/oip/es, cluster `science`), joignable depuis
|
|
4
|
+
// toutes les apps. Le suivi des listes par `keyName` (resultStore des pages
|
|
5
|
+
// de recherche) n'a pas de sens ici : les resultats reviennent a l'appelant.
|
|
6
|
+
|
|
7
|
+
import { instrumentSearchClause, searchMatchOf } from "./useOipSearchExplain";
|
|
8
|
+
|
|
9
|
+
export default function useOipElastic() {
|
|
10
|
+
const config = useRuntimeConfig();
|
|
11
|
+
//
|
|
12
|
+
// const resultsQuery = ref([] as Array<object>);
|
|
13
|
+
const queryTotalResults = ref(0 as number);
|
|
14
|
+
// const isLoadingQuery = ref(false as Boolean);
|
|
15
|
+
|
|
16
|
+
// MAKE QUEUE
|
|
17
|
+
const queryQueue = ref<Function[]>([]);
|
|
18
|
+
let isProcessingQueue = false;
|
|
19
|
+
let isDisposed = false;
|
|
20
|
+
|
|
21
|
+
// Resolvers of the promises handed out by `addToQueue`. Kept so a scope
|
|
22
|
+
// dispose can settle them instead of leaving awaiting callers hanging on a
|
|
23
|
+
// queue that will never run.
|
|
24
|
+
const pendingResolvers = new Set<() => void>();
|
|
25
|
+
|
|
26
|
+
// In-flight ES requests, aborted on dispose so navigating away doesn't leave
|
|
27
|
+
// requests running against a slow connection.
|
|
28
|
+
const inFlight = new Set<AbortController>();
|
|
29
|
+
|
|
30
|
+
// Clean up queue when the calling component/scope is destroyed
|
|
31
|
+
if (getCurrentScope()) {
|
|
32
|
+
onScopeDispose(() => {
|
|
33
|
+
isDisposed = true;
|
|
34
|
+
queryQueue.value = [];
|
|
35
|
+
isProcessingQueue = false;
|
|
36
|
+
for (const resolve of pendingResolvers) resolve();
|
|
37
|
+
pendingResolvers.clear();
|
|
38
|
+
for (const controller of inFlight) controller.abort();
|
|
39
|
+
inFlight.clear();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function processQueue() {
|
|
44
|
+
if (isProcessingQueue) return;
|
|
45
|
+
isProcessingQueue = true;
|
|
46
|
+
|
|
47
|
+
while (queryQueue.value.length > 0 && !isDisposed) {
|
|
48
|
+
const currentQuery = queryQueue.value.shift();
|
|
49
|
+
if (currentQuery && !isDisposed) {
|
|
50
|
+
try {
|
|
51
|
+
await currentQuery();
|
|
52
|
+
} catch (e) {
|
|
53
|
+
if (!isDisposed) console.error('Error executing query:', e);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
isProcessingQueue = false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Queue a query and return a promise that settles when it has actually run.
|
|
63
|
+
*
|
|
64
|
+
* Callers used to fire-and-forget this, which made their `isLoadingQuery`
|
|
65
|
+
* flag flip back to `false` in the same tick — the loader never showed and
|
|
66
|
+
* the "no results" state rendered while the request was still in flight.
|
|
67
|
+
* The returned promise is what makes `await launchQuery()` meaningful.
|
|
68
|
+
*/
|
|
69
|
+
function addToQueue(queryFunction: Function): Promise<void> {
|
|
70
|
+
if (isDisposed) return Promise.resolve();
|
|
71
|
+
|
|
72
|
+
return new Promise<void>((resolve) => {
|
|
73
|
+
const settle = () => {
|
|
74
|
+
if (pendingResolvers.delete(settle)) resolve();
|
|
75
|
+
};
|
|
76
|
+
pendingResolvers.add(settle);
|
|
77
|
+
|
|
78
|
+
queryQueue.value.push(async () => {
|
|
79
|
+
try {
|
|
80
|
+
await queryFunction();
|
|
81
|
+
} finally {
|
|
82
|
+
settle();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (queryQueue.value.length === 1) {
|
|
87
|
+
processQueue();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
93
|
+
const filterResults = ref({} as Object);
|
|
94
|
+
|
|
95
|
+
// Last ES failure, so pages can tell "the search failed" from "the search
|
|
96
|
+
// returned nothing". Without it both render as "0 results" and a network
|
|
97
|
+
// outage is indistinguishable from an empty result set.
|
|
98
|
+
const queryError = ref<string | null>(null);
|
|
99
|
+
|
|
100
|
+
// Users are regularly on slow hospital networks. A request with no bound
|
|
101
|
+
// stays in flight for minutes and the page just looks frozen, so every ES
|
|
102
|
+
// call gets an explicit ceiling.
|
|
103
|
+
const ES_TIMEOUT = 20000;
|
|
104
|
+
|
|
105
|
+
// ES calls go through the app's own server proxy (server/api/es) so the
|
|
106
|
+
// cluster domain + ApiKey never reach the browser. Auth is injected server-side.
|
|
107
|
+
const setFetchUrl = (_cluster: string | undefined, index: any) => {
|
|
108
|
+
return `/api/oip/es?cluster=science&index=${encodeURIComponent(index)}`;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const setFetchHeaders = (_cluster?: string) => {
|
|
112
|
+
return {};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Single entry point for every ES request: bounds it in time, aborts it on
|
|
117
|
+
* dispose, and records failures in `queryError`.
|
|
118
|
+
*
|
|
119
|
+
* Returns `null` on failure (never throws) so the ~60 existing call sites
|
|
120
|
+
* keep their current shape. `retry` is pinned to 0 — ofetch would otherwise
|
|
121
|
+
* replay these queries, and they are heavy enough that a retry storm is
|
|
122
|
+
* worse than a clean failure the user can act on.
|
|
123
|
+
*
|
|
124
|
+
* `signal` lets a caller cancel its own request — typeahead uses it to drop
|
|
125
|
+
* the query a previous keystroke started.
|
|
126
|
+
*
|
|
127
|
+
* `timeoutMs` raises the ceiling for deliberately heavy, user-initiated work
|
|
128
|
+
* (an export pulling hundreds of documents). The default suits the
|
|
129
|
+
* interactive queries a user is sitting in front of.
|
|
130
|
+
*
|
|
131
|
+
* Note: ofetch only honours its own `timeout` when no `signal` is passed,
|
|
132
|
+
* so the deadline is enforced here rather than delegated.
|
|
133
|
+
*/
|
|
134
|
+
async function esFetch(
|
|
135
|
+
cluster: string | undefined,
|
|
136
|
+
index: string,
|
|
137
|
+
body: any,
|
|
138
|
+
signal?: AbortSignal,
|
|
139
|
+
timeoutMs?: number
|
|
140
|
+
): Promise<any | null> {
|
|
141
|
+
if (signal?.aborted) return null;
|
|
142
|
+
|
|
143
|
+
const controller = new AbortController();
|
|
144
|
+
inFlight.add(controller);
|
|
145
|
+
|
|
146
|
+
let timedOut = false;
|
|
147
|
+
const timer = setTimeout(() => {
|
|
148
|
+
timedOut = true;
|
|
149
|
+
controller.abort();
|
|
150
|
+
}, timeoutMs ?? ES_TIMEOUT);
|
|
151
|
+
|
|
152
|
+
const onCallerAbort = () => controller.abort();
|
|
153
|
+
signal?.addEventListener('abort', onCallerAbort, { once: true });
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const res = await $fetch(setFetchUrl(cluster, index), {
|
|
157
|
+
method: 'POST',
|
|
158
|
+
headers: setFetchHeaders(cluster),
|
|
159
|
+
body,
|
|
160
|
+
signal: controller.signal,
|
|
161
|
+
retry: 0,
|
|
162
|
+
});
|
|
163
|
+
queryError.value = null;
|
|
164
|
+
return res;
|
|
165
|
+
} catch (err: any) {
|
|
166
|
+
// An abort triggered by dispose is expected — the user navigated away.
|
|
167
|
+
if (isDisposed || (err?.name === 'AbortError' && !timedOut)) return null;
|
|
168
|
+
|
|
169
|
+
queryError.value = timedOut
|
|
170
|
+
? 'timeout'
|
|
171
|
+
: err?.statusCode
|
|
172
|
+
? `http_${err.statusCode}`
|
|
173
|
+
: 'network';
|
|
174
|
+
console.error('[useOipElastic] query failed', {
|
|
175
|
+
index,
|
|
176
|
+
reason: queryError.value,
|
|
177
|
+
message: err?.message,
|
|
178
|
+
});
|
|
179
|
+
return null;
|
|
180
|
+
} finally {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
signal?.removeEventListener('abort', onCallerAbort);
|
|
183
|
+
inFlight.delete(controller);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function removeDuplicateMatchAll(queryArray: any) {
|
|
188
|
+
const hasOtherQueries = queryArray.some(
|
|
189
|
+
(item) => JSON.stringify(item) !== JSON.stringify({ match_all: {} })
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const uniqueQueryArray = [];
|
|
193
|
+
let matchAllAdded = false;
|
|
194
|
+
|
|
195
|
+
for (const item of queryArray) {
|
|
196
|
+
if (JSON.stringify(item) === JSON.stringify({ match_all: {} })) {
|
|
197
|
+
if (hasOtherQueries) continue;
|
|
198
|
+
|
|
199
|
+
if (!matchAllAdded) {
|
|
200
|
+
uniqueQueryArray.push(item);
|
|
201
|
+
matchAllAdded = true;
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
uniqueQueryArray.push(item);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return uniqueQueryArray;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Helper function to get sort values
|
|
212
|
+
function getSortValues(sortQuery: any): any[] {
|
|
213
|
+
if (!sortQuery) return [];
|
|
214
|
+
return sortQuery.values || [];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function queryElastic({
|
|
218
|
+
index,
|
|
219
|
+
take,
|
|
220
|
+
skip,
|
|
221
|
+
customQuery,
|
|
222
|
+
sortQuery,
|
|
223
|
+
keyName,
|
|
224
|
+
source,
|
|
225
|
+
highlight,
|
|
226
|
+
with_id,
|
|
227
|
+
cluster,
|
|
228
|
+
mustNot,
|
|
229
|
+
timeout,
|
|
230
|
+
explainFilter,
|
|
231
|
+
}: {
|
|
232
|
+
index: string;
|
|
233
|
+
take: any;
|
|
234
|
+
skip?: number;
|
|
235
|
+
customQuery: any;
|
|
236
|
+
sortQuery?: any;
|
|
237
|
+
keyName?: any;
|
|
238
|
+
source?: any;
|
|
239
|
+
highlight?: any;
|
|
240
|
+
with_id?: boolean;
|
|
241
|
+
cluster?: string;
|
|
242
|
+
mustNot?: any;
|
|
243
|
+
// Raise the deadline for heavy, user-initiated pulls (exports).
|
|
244
|
+
timeout?: number;
|
|
245
|
+
// Filtre de la barre de recherche a instrumenter pour le « Voir pourquoi »
|
|
246
|
+
// (cf. useSearchExplain). Chaque resultat garde alors son `_match`.
|
|
247
|
+
explainFilter?: string;
|
|
248
|
+
}) {
|
|
249
|
+
let esResults: any = {
|
|
250
|
+
results: [],
|
|
251
|
+
total: 0,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// isLoadingQuery.value = true;
|
|
255
|
+
|
|
256
|
+
// Ensure customQuery is always an array
|
|
257
|
+
const customQueryArray = Array.isArray(customQuery) ? customQuery : [customQuery];
|
|
258
|
+
|
|
259
|
+
let explainHighlight: any;
|
|
260
|
+
const queryRaw = customQueryArray
|
|
261
|
+
.map((obj: any) => {
|
|
262
|
+
if (!explainFilter || obj?.filter !== explainFilter) return obj.values;
|
|
263
|
+
const { query, highlight } = instrumentSearchClause(obj.values);
|
|
264
|
+
explainHighlight = highlight;
|
|
265
|
+
return query;
|
|
266
|
+
})
|
|
267
|
+
.filter((item: any) => item && item !== undefined);
|
|
268
|
+
|
|
269
|
+
// Sans explication, le resultat reste le `_source` tel quel.
|
|
270
|
+
const sourceOf = (x: any) => {
|
|
271
|
+
if (!explainFilter) return x._source;
|
|
272
|
+
const match = searchMatchOf(x);
|
|
273
|
+
return match ? { ...x._source, _match: match } : x._source;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const queryMustValues = removeDuplicateMatchAll(queryRaw);
|
|
277
|
+
|
|
278
|
+
// QUERY
|
|
279
|
+
let query: any = {
|
|
280
|
+
from: skip ? skip : 0,
|
|
281
|
+
_source: source ? source : true,
|
|
282
|
+
query: {
|
|
283
|
+
bool: {
|
|
284
|
+
must: queryMustValues,
|
|
285
|
+
must_not: mustNot ? mustNot : [],
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
highlight: highlight ? highlight : explainHighlight ?? {},
|
|
290
|
+
size: take ? (take.values ? take.values : take) : 10,
|
|
291
|
+
sort: getSortValues(sortQuery),
|
|
292
|
+
track_total_hits: true,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// FETCH
|
|
296
|
+
const res: any = await esFetch(cluster, index, query, undefined, timeout);
|
|
297
|
+
|
|
298
|
+
if (!isDisposed && res) {
|
|
299
|
+
{
|
|
300
|
+
// OTHERWISE USE resultsQuery as result
|
|
301
|
+
|
|
302
|
+
if (!with_id) {
|
|
303
|
+
esResults.results = res.hits.hits.map(sourceOf);
|
|
304
|
+
esResults.total = res.hits.total.value;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (with_id) {
|
|
308
|
+
esResults.results = res.hits.hits.map((x: any) => x);
|
|
309
|
+
esResults.total = res.hits.total.value;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return esResults;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
318
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
319
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
320
|
+
|
|
321
|
+
async function queryOneElastic({
|
|
322
|
+
index,
|
|
323
|
+
path,
|
|
324
|
+
id,
|
|
325
|
+
source,
|
|
326
|
+
cluster,
|
|
327
|
+
}: {
|
|
328
|
+
index: string;
|
|
329
|
+
path: any;
|
|
330
|
+
id: any;
|
|
331
|
+
source?: any;
|
|
332
|
+
cluster?: string;
|
|
333
|
+
}) {
|
|
334
|
+
let esResults: object = {};
|
|
335
|
+
|
|
336
|
+
// QUERY
|
|
337
|
+
let query: any = {
|
|
338
|
+
from: 0,
|
|
339
|
+
_source: source ? source : [],
|
|
340
|
+
query: {
|
|
341
|
+
bool: {
|
|
342
|
+
must: [{ match: { [`${path}`]: id } }],
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
size: 1,
|
|
347
|
+
|
|
348
|
+
track_total_hits: true,
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// FETCH
|
|
352
|
+
const res: any = await esFetch(cluster, index, query);
|
|
353
|
+
|
|
354
|
+
if (res) {
|
|
355
|
+
esResults = res.hits.hits.map((x: any) => x._source)[0];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return esResults;
|
|
359
|
+
}
|
|
360
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
361
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
362
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
363
|
+
|
|
364
|
+
async function queryCustomElastic({
|
|
365
|
+
index,
|
|
366
|
+
customQuery,
|
|
367
|
+
onlyOne,
|
|
368
|
+
cluster,
|
|
369
|
+
|
|
370
|
+
allAnswer,
|
|
371
|
+
with_id,
|
|
372
|
+
signal,
|
|
373
|
+
timeout,
|
|
374
|
+
}: {
|
|
375
|
+
index: string;
|
|
376
|
+
customQuery: any;
|
|
377
|
+
onlyOne?: boolean;
|
|
378
|
+
cluster?: string;
|
|
379
|
+
allAnswer?: boolean;
|
|
380
|
+
with_id?: boolean;
|
|
381
|
+
// Lets the caller cancel a superseded request (typeahead).
|
|
382
|
+
signal?: AbortSignal;
|
|
383
|
+
// Raise the deadline for heavy, user-initiated pulls (exports).
|
|
384
|
+
timeout?: number;
|
|
385
|
+
}) {
|
|
386
|
+
let esResults: any = {
|
|
387
|
+
results: [],
|
|
388
|
+
total: 0,
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// QUERY
|
|
392
|
+
let query = customQuery;
|
|
393
|
+
|
|
394
|
+
// FETCH
|
|
395
|
+
const res: any = await esFetch(cluster, index, query, signal, timeout);
|
|
396
|
+
|
|
397
|
+
if (!isDisposed && res) {
|
|
398
|
+
if (onlyOne) {
|
|
399
|
+
esResults = res.hits.hits.map((x: any) => (with_id ? x : x._source))[0];
|
|
400
|
+
} else if (allAnswer) {
|
|
401
|
+
esResults = res;
|
|
402
|
+
} else {
|
|
403
|
+
esResults.results = res.hits.hits.map((x: any) =>
|
|
404
|
+
with_id ? x : x._source
|
|
405
|
+
);
|
|
406
|
+
// ES drops `hits.total` (or changes its shape) when the caller
|
|
407
|
+
// sets `track_total_hits: false`. Treat any non-object as the
|
|
408
|
+
// raw count and fall back to 0 when the field is absent.
|
|
409
|
+
const t = res.hits.total;
|
|
410
|
+
esResults.total = typeof t === 'number' ? t : (t?.value ?? 0);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return esResults;
|
|
415
|
+
}
|
|
416
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
417
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
418
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
419
|
+
|
|
420
|
+
async function queryFilter({
|
|
421
|
+
index,
|
|
422
|
+
filters,
|
|
423
|
+
take,
|
|
424
|
+
customQuery,
|
|
425
|
+
cluster,
|
|
426
|
+
mustNot,
|
|
427
|
+
}: {
|
|
428
|
+
index: string;
|
|
429
|
+
filters: any;
|
|
430
|
+
take: number;
|
|
431
|
+
customQuery: any;
|
|
432
|
+
cluster?: string;
|
|
433
|
+
mustNot?: any;
|
|
434
|
+
}) {
|
|
435
|
+
let esResults: object = {};
|
|
436
|
+
|
|
437
|
+
// Ensure customQuery is always an array
|
|
438
|
+
const customQueryArray = Array.isArray(customQuery) ? customQuery : [customQuery];
|
|
439
|
+
|
|
440
|
+
const queryMustValues = customQueryArray
|
|
441
|
+
.filter((x: any) => x.filter != filters.name)
|
|
442
|
+
.map((obj: any) => obj.values)
|
|
443
|
+
.filter((item: any) => item && item !== undefined);
|
|
444
|
+
|
|
445
|
+
// QUERY
|
|
446
|
+
let query = {
|
|
447
|
+
from: 0,
|
|
448
|
+
query: {
|
|
449
|
+
bool: {
|
|
450
|
+
must: queryMustValues,
|
|
451
|
+
must_not: mustNot ? mustNot : [],
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
aggs: filters.agg,
|
|
456
|
+
|
|
457
|
+
size: 0,
|
|
458
|
+
track_total_hits: true,
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
// FETCH. FAS chose the aggregation shape from the current route (/pubmed,
|
|
462
|
+
// /euct); a layer view has no route of its own, the index says the same.
|
|
463
|
+
const currentPath = index.includes('pubmed') ? '/pubmed' : index.includes('euct') ? '/euct' : '';
|
|
464
|
+
const res: any = await esFetch(cluster, index, query);
|
|
465
|
+
|
|
466
|
+
if (!isDisposed && res) {
|
|
467
|
+
try {
|
|
468
|
+
if(filters.path === 'diseases.icd10.combined_label' && currentPath.includes('pubmed')){
|
|
469
|
+
esResults = res.aggregations['diseases.icd10'][
|
|
470
|
+
'diseases.icd10.combined_label'
|
|
471
|
+
].buckets.map((x: { key: any }) => x.key);
|
|
472
|
+
|
|
473
|
+
}
|
|
474
|
+
else if(filters.path === 'diseases.icd10.combined_label' && currentPath.includes('euct')){
|
|
475
|
+
esResults = res.aggregations['diseases.icd10.combined_label'].buckets.map((x: { key: any }) => x.key);
|
|
476
|
+
|
|
477
|
+
}
|
|
478
|
+
else if(filters.path === 'diseases_nested.icd10_combined_label' && currentPath.includes('euct')){
|
|
479
|
+
esResults = res.aggregations['diseases_nested']['icd10_combined_label'].buckets.map((x: { key: any }) => x.key);
|
|
480
|
+
|
|
481
|
+
}
|
|
482
|
+
else if(filters.path === 'diseases.icd10.combined_label'){
|
|
483
|
+
esResults = res.aggregations['diseases'][
|
|
484
|
+
'diseases.icd10.combined_label'
|
|
485
|
+
].buckets.map((x: { key: any }) => x.key);
|
|
486
|
+
|
|
487
|
+
} else if(filters.path === 'diseases_nested.icd10_nested.icd10_combined_label'){
|
|
488
|
+
esResults = res.aggregations['diseases_nested'][
|
|
489
|
+
'icd10_nested'
|
|
490
|
+
].icd10_combined_label.buckets.map((x: { key: any }) => x.key);
|
|
491
|
+
} else if(filters.path === 'diseases.record_diseases.section_label'){
|
|
492
|
+
esResults = res.aggregations.diseases.record_diseases.section_label.buckets.map((x: { key: any }) => x.key);
|
|
493
|
+
}
|
|
494
|
+
else if (filters.isNested) {
|
|
495
|
+
esResults = res.aggregations[filters.path.split('.')[0]][
|
|
496
|
+
filters.path
|
|
497
|
+
].buckets.map((x: { key: any }) => x.key);
|
|
498
|
+
} else {
|
|
499
|
+
esResults = res.aggregations[filters.path].buckets.map(
|
|
500
|
+
(x: { key: any }) => x.key
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
} catch (err: any) {
|
|
504
|
+
// The aggregation came back in a shape this branch didn't expect —
|
|
505
|
+
// a mapping change, not a network problem. Report it as such rather
|
|
506
|
+
// than letting it read as an empty filter.
|
|
507
|
+
queryError.value = 'unexpected_aggregation';
|
|
508
|
+
console.error('[useOipElastic] queryFilter: unexpected aggregation shape', {
|
|
509
|
+
index,
|
|
510
|
+
path: filters.path,
|
|
511
|
+
message: err?.message,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return esResults;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async function queryAggregations({
|
|
520
|
+
index,
|
|
521
|
+
queryFilter,
|
|
522
|
+
aggs,
|
|
523
|
+
cluster,
|
|
524
|
+
isNested,
|
|
525
|
+
allAnswer,
|
|
526
|
+
}: {
|
|
527
|
+
index: string;
|
|
528
|
+
queryFilter: any;
|
|
529
|
+
aggs: any;
|
|
530
|
+
cluster?: string;
|
|
531
|
+
isNested?: boolean;
|
|
532
|
+
allAnswer?: boolean;
|
|
533
|
+
}) {
|
|
534
|
+
let esResults: object = {};
|
|
535
|
+
|
|
536
|
+
// QUERY
|
|
537
|
+
let query: any = {
|
|
538
|
+
from: 0,
|
|
539
|
+
query: queryFilter,
|
|
540
|
+
aggs: aggs,
|
|
541
|
+
size: 0,
|
|
542
|
+
track_total_hits: true,
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const aggsKey = Object.keys(aggs)[0];
|
|
546
|
+
|
|
547
|
+
// FETCH
|
|
548
|
+
const res: any = await esFetch(cluster, index, query);
|
|
549
|
+
|
|
550
|
+
if (!isDisposed && res) {
|
|
551
|
+
if (allAnswer) {
|
|
552
|
+
esResults = res.aggregations;
|
|
553
|
+
} else {
|
|
554
|
+
if (isNested) {
|
|
555
|
+
esResults = res.aggregations[aggsKey][aggsKey].buckets.map(
|
|
556
|
+
(x: { key: any }) => x.key
|
|
557
|
+
);
|
|
558
|
+
} else {
|
|
559
|
+
esResults = res.aggregations[aggsKey].buckets.map(
|
|
560
|
+
(x: { key: any }) => x.key
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return esResults;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
570
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
571
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
572
|
+
|
|
573
|
+
async function querySearchFilter({
|
|
574
|
+
index,
|
|
575
|
+
filters,
|
|
576
|
+
take,
|
|
577
|
+
customQuery,
|
|
578
|
+
cluster,
|
|
579
|
+
mustNot,
|
|
580
|
+
}: {
|
|
581
|
+
index: string;
|
|
582
|
+
filters: any;
|
|
583
|
+
take: number;
|
|
584
|
+
customQuery: any;
|
|
585
|
+
cluster?: string;
|
|
586
|
+
mustNot?: any;
|
|
587
|
+
}) {
|
|
588
|
+
let esResults: object = {};
|
|
589
|
+
|
|
590
|
+
// Ensure customQuery is always an array
|
|
591
|
+
const customQueryArray = Array.isArray(customQuery) ? customQuery : [customQuery];
|
|
592
|
+
|
|
593
|
+
const queryMustValues = customQueryArray
|
|
594
|
+
.filter((x: any) => x.filter != filters.name)
|
|
595
|
+
.map((obj: any) => obj.values)
|
|
596
|
+
.filter((item: any) => item !== undefined);
|
|
597
|
+
|
|
598
|
+
let query: any = {
|
|
599
|
+
from: 0,
|
|
600
|
+
query: {
|
|
601
|
+
bool: {
|
|
602
|
+
must: [
|
|
603
|
+
{
|
|
604
|
+
bool: {
|
|
605
|
+
must: queryMustValues,
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
filters.searchQuery,
|
|
609
|
+
],
|
|
610
|
+
must_not: mustNot ? mustNot : [],
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
|
|
614
|
+
aggs: filters.agg,
|
|
615
|
+
|
|
616
|
+
size: 0,
|
|
617
|
+
|
|
618
|
+
track_total_hits: true,
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
// FETCH
|
|
622
|
+
const res: any = await esFetch(cluster, index, query);
|
|
623
|
+
|
|
624
|
+
if (!isDisposed && res) {
|
|
625
|
+
if (filters.isNested) {
|
|
626
|
+
esResults = res.aggregations[filters.path][filters.path].buckets.map(
|
|
627
|
+
(x: { key: any }) => x.key
|
|
628
|
+
);
|
|
629
|
+
} else {
|
|
630
|
+
esResults = res.aggregations[filters.path].buckets.map(
|
|
631
|
+
(x: { key: any }) => x.key
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return esResults;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
640
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
641
|
+
return {
|
|
642
|
+
queryElastic,
|
|
643
|
+
|
|
644
|
+
// isLoadingQuery,
|
|
645
|
+
queryTotalResults,
|
|
646
|
+
// resultsQuery,
|
|
647
|
+
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
648
|
+
queryFilter,
|
|
649
|
+
filterResults,
|
|
650
|
+
queryCustomElastic,
|
|
651
|
+
querySearchFilter,
|
|
652
|
+
|
|
653
|
+
queryOneElastic,
|
|
654
|
+
queryAggregations,
|
|
655
|
+
addToQueue,
|
|
656
|
+
queryError,
|
|
657
|
+
};
|
|
658
|
+
}
|