@tekkare/romulus 0.1.53 → 0.1.54
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
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Les options d'un filtre a referentiel long, cherchees dans l'index.
|
|
3
|
+
*
|
|
4
|
+
* Un filtre agrege un champ (les marques, les molecules) et cherche sur
|
|
5
|
+
* d'autres. La regle qui compte est la : sur un index ou une ligne porte a la
|
|
6
|
+
* fois la marque, la molecule, la classe et le laboratoire, chercher dans un
|
|
7
|
+
* filtre doit interroger AUSSI les champs freres, sans changer ce que le
|
|
8
|
+
* filtre remonte. « keytruda » tape dans le filtre molecule trouve la ligne
|
|
9
|
+
* par sa marque et l'agregation en sort PEMBROLIZUMAB ; « pembrolizumab »
|
|
10
|
+
* tape dans le filtre marque en sort Keytruda. Sans cela l'utilisateur doit
|
|
11
|
+
* connaitre le nom qu'il cherche dans le vocabulaire exact du filtre, ce qui
|
|
12
|
+
* est justement ce qu'il vient demander.
|
|
13
|
+
*
|
|
14
|
+
* Le module ne parle pas au moteur : il ecrit le corps de la requete et relit
|
|
15
|
+
* les seaux. Le transport (proxy, cache, index) reste a l'application.
|
|
16
|
+
*/
|
|
17
|
+
export interface RmFilterOption {
|
|
18
|
+
label: string;
|
|
19
|
+
value: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RmFilterOptionsSpec {
|
|
22
|
+
/**
|
|
23
|
+
* Ce que le filtre agrege. Un champ : la valeur est son propre libelle
|
|
24
|
+
* (`brand.keyword`). Deux champs `[libelle, valeur]` : le premier s'affiche,
|
|
25
|
+
* le second est ce que l'analyse filtre (un libelle ATC et son code).
|
|
26
|
+
*/
|
|
27
|
+
field: string | [string, string];
|
|
28
|
+
/**
|
|
29
|
+
* Champs interroges par la saisie, dans l'ordre : le champ propre au filtre
|
|
30
|
+
* d'abord, ses synonymes ensuite. Champs analyses (`brand`), pas leur
|
|
31
|
+
* `.keyword` : un `.keyword` ne repond pas a une recherche partielle.
|
|
32
|
+
*/
|
|
33
|
+
search: string[];
|
|
34
|
+
/** La saisie, telle qu'elle est tapee. Vide, tout le referentiel remonte. */
|
|
35
|
+
input: string;
|
|
36
|
+
/**
|
|
37
|
+
* Plafond de la liste. Au-dela, c'est la recherche qui trie : une liste
|
|
38
|
+
* coupee a cent laisse croire que ce qui suit n'existe pas.
|
|
39
|
+
*/
|
|
40
|
+
size?: number;
|
|
41
|
+
}
|
|
42
|
+
/** Le corps de la requete d'agregation, a poster tel quel sur l'index. */
|
|
43
|
+
export declare function rmFilterOptionsQuery(spec: RmFilterOptionsSpec): {
|
|
44
|
+
size: number;
|
|
45
|
+
query: {
|
|
46
|
+
bool: {
|
|
47
|
+
must: {
|
|
48
|
+
query_string: {
|
|
49
|
+
fields: string[];
|
|
50
|
+
query: string;
|
|
51
|
+
analyze_wildcard: boolean;
|
|
52
|
+
default_operator: string;
|
|
53
|
+
};
|
|
54
|
+
}[];
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
aggs: {
|
|
58
|
+
count: {
|
|
59
|
+
multi_terms: {
|
|
60
|
+
terms: {
|
|
61
|
+
field: string;
|
|
62
|
+
}[];
|
|
63
|
+
size: number;
|
|
64
|
+
order: {
|
|
65
|
+
_key: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
terms?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
terms: {
|
|
71
|
+
field: string;
|
|
72
|
+
size: number;
|
|
73
|
+
order: {
|
|
74
|
+
_key: string;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
multi_terms?: undefined;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Les options, relues dans la reponse du moteur. */
|
|
82
|
+
export declare function rmFilterOptions(response: any): RmFilterOption[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const DEFAULT_SIZE = 5e3;
|
|
2
|
+
function wildcard(input) {
|
|
3
|
+
return ("*" + input + "*").normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
4
|
+
}
|
|
5
|
+
export function rmFilterOptionsQuery(spec) {
|
|
6
|
+
const size = spec.size ?? DEFAULT_SIZE;
|
|
7
|
+
const count = Array.isArray(spec.field) ? {
|
|
8
|
+
multi_terms: {
|
|
9
|
+
terms: spec.field.map((field) => ({ field })),
|
|
10
|
+
size,
|
|
11
|
+
order: { _key: "asc" }
|
|
12
|
+
}
|
|
13
|
+
} : { terms: { field: spec.field, size, order: { _key: "asc" } } };
|
|
14
|
+
return {
|
|
15
|
+
size: 0,
|
|
16
|
+
query: {
|
|
17
|
+
bool: {
|
|
18
|
+
must: [
|
|
19
|
+
{
|
|
20
|
+
query_string: {
|
|
21
|
+
// Plusieurs champs valent un OU : la ligne repond des qu'un seul
|
|
22
|
+
// d'entre eux porte la saisie. C'est ce qui rend les synonymes.
|
|
23
|
+
fields: spec.search,
|
|
24
|
+
query: wildcard(spec.input),
|
|
25
|
+
analyze_wildcard: true,
|
|
26
|
+
default_operator: "AND"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
aggs: { count }
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function rmFilterOptions(response) {
|
|
36
|
+
const buckets = response?.aggregations?.count?.buckets ?? [];
|
|
37
|
+
return buckets.map(
|
|
38
|
+
(bucket) => Array.isArray(bucket.key) ? { label: String(bucket.key[0]), value: String(bucket.key[1]) } : { label: String(bucket.key), value: String(bucket.key) }
|
|
39
|
+
);
|
|
40
|
+
}
|