mbd-studio-sdk 2.1.2 → 2.2.1
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/StudioConfig.js +18 -105
- package/V1/Studio.js +17 -126
- package/V1/features/Features.js +8 -123
- package/V1/ranking/Ranking.js +22 -241
- package/V1/scoring/Scoring.js +4 -92
- package/V1/search/Search.js +39 -387
- package/V1/search/filters/ConsoleAccountFilter.js +0 -10
- package/V1/search/filters/CustomFilter.js +0 -9
- package/V1/search/filters/DateFilter.js +1 -13
- package/V1/search/filters/Filter.js +1 -13
- package/V1/search/filters/GeoFilter.js +0 -9
- package/V1/search/filters/GroupBoostFilter.js +0 -14
- package/V1/search/filters/IsNullFilter.js +0 -8
- package/V1/search/filters/MatchFilter.js +0 -9
- package/V1/search/filters/NotNullFilter.js +0 -8
- package/V1/search/filters/NumericFilter.js +0 -10
- package/V1/search/filters/TermFilter.js +0 -9
- package/V1/search/filters/TermsFilter.js +0 -9
- package/V1/search/filters/TermsLookupFilter.js +0 -11
- package/V1/utils/indexUtils.js +0 -5
- package/index.js +0 -1
- package/package.json +1 -1
package/V1/search/Search.js
CHANGED
|
@@ -1,43 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {{ field: string, order: "asc" | "desc" }} SortBy
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
import {
|
|
6
|
-
Filter,
|
|
7
|
-
|
|
8
|
-
TermsFilter,
|
|
9
|
-
NumericFilter,
|
|
10
|
-
MatchFilter,
|
|
11
|
-
GeoFilter,
|
|
12
|
-
DateFilter,
|
|
13
|
-
IsNullFilter,
|
|
14
|
-
NotNullFilter,
|
|
15
|
-
CustomFilter,
|
|
16
|
-
GroupBoostFilter,
|
|
17
|
-
TermsLookupFilter,
|
|
18
|
-
ConsoleAccountFilter,
|
|
2
|
+
Filter, TermFilter, TermsFilter, NumericFilter, MatchFilter, GeoFilter, DateFilter,
|
|
3
|
+
IsNullFilter, NotNullFilter, CustomFilter, GroupBoostFilter, TermsLookupFilter, ConsoleAccountFilter,
|
|
19
4
|
} from './filters/index.js';
|
|
20
5
|
|
|
21
|
-
/**
|
|
22
|
-
* Search client for MBD Studio SDK.
|
|
23
|
-
* Fluent API: methods return the instance for chaining.
|
|
24
|
-
*/
|
|
25
6
|
export class Search {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
7
|
+
_index = null;
|
|
8
|
+
_es_query = null;
|
|
9
|
+
_size = 100;
|
|
10
|
+
_only_ids = false;
|
|
11
|
+
_include_vector = false;
|
|
12
|
+
_select_fields = null;
|
|
13
|
+
_text = null;
|
|
14
|
+
_vector = null;
|
|
15
|
+
_sort_by = null;
|
|
16
|
+
_include = [];
|
|
17
|
+
_exclude = [];
|
|
18
|
+
_boost = [];
|
|
19
|
+
_active_array = null;
|
|
20
|
+
lastCall = null;
|
|
21
|
+
lastResult = null;
|
|
41
22
|
constructor(options) {
|
|
42
23
|
if (!options || typeof options !== 'object') {
|
|
43
24
|
throw new Error('Search: options object is required');
|
|
@@ -55,91 +36,20 @@ export class Search {
|
|
|
55
36
|
this._log = typeof log === 'function' ? log : console.log.bind(console);
|
|
56
37
|
this._show = typeof show === 'function' ? show : console.log.bind(console);
|
|
57
38
|
}
|
|
58
|
-
|
|
59
|
-
/** @type {string | null} */
|
|
60
|
-
_index = null;
|
|
61
|
-
|
|
62
|
-
/** @type {object | null} - Raw ES query for es_query endpoint */
|
|
63
|
-
_es_query = null;
|
|
64
|
-
|
|
65
|
-
/** @type {number} */
|
|
66
|
-
_size = 100;
|
|
67
|
-
|
|
68
|
-
/** @type {boolean} */
|
|
69
|
-
_only_ids = false;
|
|
70
|
-
|
|
71
|
-
/** @type {boolean} */
|
|
72
|
-
_include_vector = false;
|
|
73
|
-
|
|
74
|
-
/** @type {string[] | null} */
|
|
75
|
-
_select_fields = null;
|
|
76
|
-
|
|
77
|
-
/** @type {string | null} */
|
|
78
|
-
_text = null;
|
|
79
|
-
|
|
80
|
-
/** @type {number[] | null} */
|
|
81
|
-
_vector = null;
|
|
82
|
-
|
|
83
|
-
/** @type {SortBy | null} */
|
|
84
|
-
_sort_by = null;
|
|
85
|
-
|
|
86
|
-
/** @type {Filter[]} */
|
|
87
|
-
_include = [];
|
|
88
|
-
|
|
89
|
-
/** @type {Filter[]} */
|
|
90
|
-
_exclude = [];
|
|
91
|
-
|
|
92
|
-
/** @type {Filter[]} */
|
|
93
|
-
_boost = [];
|
|
94
|
-
|
|
95
|
-
/** @type {Filter[] | null} */
|
|
96
|
-
_active_array = null;
|
|
97
|
-
|
|
98
|
-
/** @type {{ endpoint: string, payload: object } | null} */
|
|
99
|
-
lastCall = null;
|
|
100
|
-
|
|
101
|
-
/** @type {object | null} */
|
|
102
|
-
lastResult = null;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Return the endpoint path for the current query configuration.
|
|
107
|
-
* es_query if set; semantic if text or vector is set; boost if any boost filter; otherwise filter_and_sort.
|
|
108
|
-
* @returns {string}
|
|
109
|
-
*/
|
|
110
39
|
getEndpoint() {
|
|
111
40
|
if (this._es_query != null) return '/search/es_query';
|
|
112
|
-
const hasTextOrVector =
|
|
113
|
-
(typeof this._text === 'string' && this._text.length > 0) ||
|
|
114
|
-
(Array.isArray(this._vector) && this._vector.length > 0);
|
|
41
|
+
const hasTextOrVector = (typeof this._text === 'string' && this._text.length > 0) || (Array.isArray(this._vector) && this._vector.length > 0);
|
|
115
42
|
if (hasTextOrVector) return '/search/semantic';
|
|
116
43
|
if (this._boost.length > 0) return '/search/boost';
|
|
117
44
|
return '/search/filter_and_sort';
|
|
118
45
|
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Build the request payload for the current query.
|
|
122
|
-
* @returns {object}
|
|
123
|
-
*/
|
|
124
46
|
getPayload() {
|
|
125
47
|
const endpoint = this.getEndpoint();
|
|
126
48
|
if (endpoint === '/search/es_query') {
|
|
127
|
-
return {
|
|
128
|
-
index: this._index,
|
|
129
|
-
origin: this._origin,
|
|
130
|
-
feed_type: 'es_query',
|
|
131
|
-
query: this._es_query,
|
|
132
|
-
};
|
|
49
|
+
return { index: this._index, origin: this._origin, feed_type: 'es_query', query: this._es_query };
|
|
133
50
|
}
|
|
134
|
-
const feedType =
|
|
135
|
-
endpoint === '/search/semantic'
|
|
136
|
-
? 'semantic'
|
|
137
|
-
: endpoint === '/search/boost'
|
|
138
|
-
? 'boost'
|
|
139
|
-
: 'filter_and_sort';
|
|
140
|
-
|
|
51
|
+
const feedType = endpoint === '/search/semantic' ? 'semantic' : endpoint === '/search/boost' ? 'boost' : 'filter_and_sort';
|
|
141
52
|
const serializeFilters = (arr) => arr.map((f) => ({ ...f }));
|
|
142
|
-
|
|
143
53
|
const payload = {
|
|
144
54
|
index: this._index,
|
|
145
55
|
origin: this._origin,
|
|
@@ -149,29 +59,16 @@ export class Search {
|
|
|
149
59
|
include: serializeFilters(this._include),
|
|
150
60
|
exclude: serializeFilters(this._exclude),
|
|
151
61
|
};
|
|
152
|
-
|
|
153
|
-
if (feedType === '
|
|
154
|
-
payload.boost = serializeFilters(this._boost);
|
|
155
|
-
}
|
|
156
|
-
if (feedType === 'filter_and_sort' && this._sort_by) {
|
|
157
|
-
payload.sort_by = this._sort_by;
|
|
158
|
-
}
|
|
62
|
+
if (feedType === 'boost') payload.boost = serializeFilters(this._boost);
|
|
63
|
+
if (feedType === 'filter_and_sort' && this._sort_by) payload.sort_by = this._sort_by;
|
|
159
64
|
if (feedType === 'semantic') {
|
|
160
65
|
if (typeof this._text === 'string' && this._text.length > 0) payload.text = this._text;
|
|
161
66
|
if (Array.isArray(this._vector) && this._vector.length > 0) payload.vector = this._vector;
|
|
162
67
|
}
|
|
163
68
|
if (this._only_ids) payload.only_ids = true;
|
|
164
|
-
if (Array.isArray(this._select_fields) && this._select_fields.length > 0)
|
|
165
|
-
payload.select_fields = this._select_fields;
|
|
166
|
-
}
|
|
167
|
-
|
|
69
|
+
if (Array.isArray(this._select_fields) && this._select_fields.length > 0) payload.select_fields = this._select_fields;
|
|
168
70
|
return payload;
|
|
169
71
|
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Execute the search request. Sets lastCall and lastResult on success; throws on error.
|
|
173
|
-
* @returns {Promise<object>}
|
|
174
|
-
*/
|
|
175
72
|
async execute() {
|
|
176
73
|
if (!this._index || typeof this._index !== 'string' || !this._index.trim()) {
|
|
177
74
|
throw new Error('Search.execute: index must be set (call index(name) first)');
|
|
@@ -187,10 +84,7 @@ export class Search {
|
|
|
187
84
|
const startTime = performance.now();
|
|
188
85
|
const response = await fetch(url, {
|
|
189
86
|
method: 'POST',
|
|
190
|
-
headers: {
|
|
191
|
-
'Content-Type': 'application/json',
|
|
192
|
-
Authorization: `Bearer ${this._apiKey}`,
|
|
193
|
-
},
|
|
87
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this._apiKey}` },
|
|
194
88
|
body: JSON.stringify(payload),
|
|
195
89
|
});
|
|
196
90
|
const frontendTime = Math.round(performance.now() - startTime);
|
|
@@ -210,13 +104,8 @@ export class Search {
|
|
|
210
104
|
result.took_frontend = frontendTime;
|
|
211
105
|
this.lastCall = { endpoint, payload };
|
|
212
106
|
this.lastResult = result;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
throw new Error('Search.execute: result.result is undefined');
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Log query infos (same as InfoColumn.js)
|
|
219
|
-
const res = result.result ;
|
|
107
|
+
if (!result.result) throw new Error('Search.execute: result.result is undefined');
|
|
108
|
+
const res = result.result;
|
|
220
109
|
const infos = {
|
|
221
110
|
total_hits: res?.total_hits ?? 0,
|
|
222
111
|
fetched_hits: res?.hits?.length ?? 0,
|
|
@@ -234,12 +123,6 @@ export class Search {
|
|
|
234
123
|
this._log(` max_score: ${infos.max_score}`);
|
|
235
124
|
return res.hits;
|
|
236
125
|
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Look up a document by ID. Uses the index set by index().
|
|
240
|
-
* @param {string} docId - Document ID
|
|
241
|
-
* @returns {Promise<object>} Full response (use result.result for the document)
|
|
242
|
-
*/
|
|
243
126
|
async lookup(docId) {
|
|
244
127
|
if (!this._index || typeof this._index !== 'string' || !this._index.trim()) {
|
|
245
128
|
throw new Error('Search.lookup: index must be set (call index(name) first)');
|
|
@@ -253,9 +136,7 @@ export class Search {
|
|
|
253
136
|
const startTime = performance.now();
|
|
254
137
|
const response = await fetch(url, {
|
|
255
138
|
method: 'GET',
|
|
256
|
-
headers: {
|
|
257
|
-
Authorization: `Bearer ${this._apiKey}`,
|
|
258
|
-
},
|
|
139
|
+
headers: { Authorization: `Bearer ${this._apiKey}` },
|
|
259
140
|
});
|
|
260
141
|
const frontendTime = Math.round(performance.now() - startTime);
|
|
261
142
|
if (!response.ok) {
|
|
@@ -276,12 +157,6 @@ export class Search {
|
|
|
276
157
|
this.lastResult = result;
|
|
277
158
|
return result;
|
|
278
159
|
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Set the index to search.
|
|
282
|
-
* @param {string} selected_index - Index name to search
|
|
283
|
-
* @returns {this}
|
|
284
|
-
*/
|
|
285
160
|
index(selected_index) {
|
|
286
161
|
if (typeof selected_index !== 'string' || !selected_index.trim()) {
|
|
287
162
|
throw new Error('Search.index: selected_index must be a non-empty string');
|
|
@@ -289,12 +164,6 @@ export class Search {
|
|
|
289
164
|
this._index = selected_index.trim();
|
|
290
165
|
return this;
|
|
291
166
|
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Set the number of results to return.
|
|
295
|
-
* @param {number} size - Number of results (must be > 0 and < 2000)
|
|
296
|
-
* @returns {this}
|
|
297
|
-
*/
|
|
298
167
|
size(size) {
|
|
299
168
|
const n = Number(size);
|
|
300
169
|
if (!Number.isInteger(n) || n <= 0 || n >= 2000) {
|
|
@@ -303,79 +172,35 @@ export class Search {
|
|
|
303
172
|
this._size = n;
|
|
304
173
|
return this;
|
|
305
174
|
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Set whether to return only IDs in results. Call with no argument or true to enable, false to disable.
|
|
309
|
-
* @param {boolean} [value=true] - When omitted, sets to true
|
|
310
|
-
* @returns {this}
|
|
311
|
-
*/
|
|
312
175
|
onlyIds(value) {
|
|
313
176
|
this._only_ids = value == null ? true : Boolean(value);
|
|
314
177
|
return this;
|
|
315
178
|
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Set whether to include vectors in results. Call with no argument or true to enable, false to disable.
|
|
319
|
-
* @param {boolean} [value=true] - When omitted, sets to true
|
|
320
|
-
* @returns {this}
|
|
321
|
-
*/
|
|
322
179
|
includeVectors(value) {
|
|
323
180
|
this._include_vector = value == null ? true : Boolean(value);
|
|
324
181
|
return this;
|
|
325
182
|
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Set which fields to include in results. Pass an array of field names; pass null to clear.
|
|
329
|
-
* @param {string[] | null} fields - Array of field names, or null
|
|
330
|
-
* @returns {this}
|
|
331
|
-
*/
|
|
332
183
|
selectFields(fields) {
|
|
333
184
|
if (fields === null) {
|
|
334
185
|
this._select_fields = null;
|
|
335
186
|
return this;
|
|
336
187
|
}
|
|
337
|
-
if (!Array.isArray(fields))
|
|
338
|
-
throw new Error('Search.selectFields: fields must be an array of strings or null');
|
|
339
|
-
}
|
|
188
|
+
if (!Array.isArray(fields)) throw new Error('Search.selectFields: fields must be an array of strings or null');
|
|
340
189
|
const normalized = fields.map((f) => (typeof f === 'string' ? f.trim() : String(f)));
|
|
341
|
-
if (normalized.some((f) => !f))
|
|
342
|
-
throw new Error('Search.selectFields: each field must be a non-empty string');
|
|
343
|
-
}
|
|
190
|
+
if (normalized.some((f) => !f)) throw new Error('Search.selectFields: each field must be a non-empty string');
|
|
344
191
|
this._select_fields = normalized;
|
|
345
192
|
return this;
|
|
346
193
|
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Set the text query for search.
|
|
350
|
-
* @param {string} text - Text to search
|
|
351
|
-
* @returns {this}
|
|
352
|
-
*/
|
|
353
194
|
text(text) {
|
|
354
|
-
if (typeof text !== 'string' || !text.trim())
|
|
355
|
-
throw new Error('Search.text: text must be a non-empty string');
|
|
356
|
-
}
|
|
195
|
+
if (typeof text !== 'string' || !text.trim()) throw new Error('Search.text: text must be a non-empty string');
|
|
357
196
|
this._text = text.trim();
|
|
358
197
|
return this;
|
|
359
198
|
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Set the vector for vector search.
|
|
363
|
-
* @param {number[]} vector - Vector embedding
|
|
364
|
-
* @returns {this}
|
|
365
|
-
*/
|
|
366
199
|
vector(vector) {
|
|
367
|
-
if (!Array.isArray(vector))
|
|
368
|
-
throw new Error('Search.vector: vector must be an array of numbers');
|
|
369
|
-
}
|
|
200
|
+
if (!Array.isArray(vector)) throw new Error('Search.vector: vector must be an array of numbers');
|
|
370
201
|
this._vector = vector;
|
|
371
202
|
return this;
|
|
372
203
|
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Set a raw Elasticsearch query for the es_query endpoint. Call index() before execute().
|
|
376
|
-
* @param {object} rawQuery - Raw ES query object (e.g. { query: {...}, sort: [...], size: 10 })
|
|
377
|
-
* @returns {this}
|
|
378
|
-
*/
|
|
379
204
|
esQuery(rawQuery) {
|
|
380
205
|
if (rawQuery == null || typeof rawQuery !== 'object' || Array.isArray(rawQuery)) {
|
|
381
206
|
throw new Error('Search.esQuery: rawQuery must be a plain object');
|
|
@@ -383,291 +208,118 @@ export class Search {
|
|
|
383
208
|
this._es_query = rawQuery;
|
|
384
209
|
return this;
|
|
385
210
|
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* Set sort by field and direction.
|
|
389
|
-
* @param {string} field - Field name to sort by
|
|
390
|
-
* @param {"asc" | "desc"} [direction="desc"] - Sort direction
|
|
391
|
-
* @returns {this}
|
|
392
|
-
*/
|
|
393
211
|
sortBy(field, direction = 'desc') {
|
|
394
|
-
if (typeof field !== 'string' || !field.trim())
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
if (direction !== 'asc' && direction !== 'desc') {
|
|
398
|
-
throw new Error('Search.sortBy: direction must be "asc" or "desc"');
|
|
399
|
-
}
|
|
212
|
+
if (typeof field !== 'string' || !field.trim()) throw new Error('Search.sortBy: field must be a non-empty string');
|
|
213
|
+
if (direction !== 'asc' && direction !== 'desc') throw new Error('Search.sortBy: direction must be "asc" or "desc"');
|
|
400
214
|
this._sort_by = { field: field.trim(), order: direction };
|
|
401
215
|
return this;
|
|
402
216
|
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Set the active array to include. Subsequent add operations will target _include.
|
|
406
|
-
* @returns {this}
|
|
407
|
-
*/
|
|
408
217
|
include() {
|
|
409
218
|
this._active_array = this._include;
|
|
410
219
|
return this;
|
|
411
220
|
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Set the active array to exclude. Subsequent add operations will target _exclude.
|
|
415
|
-
* @returns {this}
|
|
416
|
-
*/
|
|
417
221
|
exclude() {
|
|
418
222
|
this._active_array = this._exclude;
|
|
419
223
|
return this;
|
|
420
224
|
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Set the active array to boost. Subsequent add operations will target _boost.
|
|
424
|
-
* @returns {this}
|
|
425
|
-
*/
|
|
426
225
|
boost() {
|
|
427
226
|
this._active_array = this._boost;
|
|
428
227
|
return this;
|
|
429
228
|
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Ensure an active array is set. Throws if include(), exclude() or boost() was not called.
|
|
433
|
-
* @private
|
|
434
|
-
*/
|
|
435
229
|
_requireActiveArray() {
|
|
436
|
-
if (this._active_array === null)
|
|
437
|
-
throw new Error(
|
|
438
|
-
'Search: call include(), exclude(), or boost() before adding filters'
|
|
439
|
-
);
|
|
440
|
-
}
|
|
230
|
+
if (this._active_array === null) throw new Error('Search: call include(), exclude(), or boost() before adding filters');
|
|
441
231
|
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* When the active array is _boost, require a non-null boost (group_boost filter type is exempt).
|
|
445
|
-
* @private
|
|
446
|
-
* @param {number | null} boost - Boost value for convenience methods
|
|
447
|
-
*/
|
|
448
232
|
_requireBoostForBoostArray(boost) {
|
|
449
233
|
if (this._active_array === this._boost && boost == null) {
|
|
450
|
-
throw new Error(
|
|
451
|
-
'Search: when adding to boost array, a non-null boost is required'
|
|
452
|
-
);
|
|
234
|
+
throw new Error('Search: when adding to boost array, a non-null boost is required');
|
|
453
235
|
}
|
|
454
236
|
}
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Add any Filter instance to the active array (include, exclude, or boost).
|
|
458
|
-
* @param {Filter} filterInstance - A filter instance (TermFilter, NumericFilter, etc.)
|
|
459
|
-
* @returns {this}
|
|
460
|
-
*/
|
|
461
237
|
filter(filterInstance) {
|
|
462
238
|
this._requireActiveArray();
|
|
463
239
|
if (filterInstance == null || !(filterInstance instanceof Filter)) {
|
|
464
240
|
throw new Error('Search.filter: argument must be a Filter instance');
|
|
465
241
|
}
|
|
466
|
-
if (
|
|
467
|
-
|
|
468
|
-
filterInstance.filter !== 'group_boost' &&
|
|
469
|
-
filterInstance.boost == null
|
|
470
|
-
) {
|
|
471
|
-
throw new Error(
|
|
472
|
-
'Search: when adding to boost array, the filter must have a non-null boost (group_boost is exempt)'
|
|
473
|
-
);
|
|
242
|
+
if (this._active_array === this._boost && filterInstance.filter !== 'group_boost' && filterInstance.boost == null) {
|
|
243
|
+
throw new Error('Search: when adding to boost array, the filter must have a non-null boost (group_boost is exempt)');
|
|
474
244
|
}
|
|
475
245
|
this._active_array.push(filterInstance);
|
|
476
246
|
return this;
|
|
477
247
|
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Add a term filter (exact match on a single value).
|
|
481
|
-
* @param {string} field - Field to filter on
|
|
482
|
-
* @param {string} value - Exact value to match
|
|
483
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
484
|
-
* @returns {this}
|
|
485
|
-
*/
|
|
486
248
|
term(field, value, boost = null) {
|
|
487
249
|
this._requireActiveArray();
|
|
488
250
|
this._requireBoostForBoostArray(boost);
|
|
489
251
|
this._active_array.push(new TermFilter(field, value, boost));
|
|
490
252
|
return this;
|
|
491
253
|
}
|
|
492
|
-
|
|
493
|
-
/**
|
|
494
|
-
* Add a terms filter (at least one of the values must match).
|
|
495
|
-
* @param {string} field - Field to filter on
|
|
496
|
-
* @param {string[]} values - Values to match
|
|
497
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
498
|
-
* @returns {this}
|
|
499
|
-
*/
|
|
500
254
|
terms(field, values, boost = null) {
|
|
501
255
|
this._requireActiveArray();
|
|
502
256
|
this._requireBoostForBoostArray(boost);
|
|
503
257
|
this._active_array.push(new TermsFilter(field, values, boost));
|
|
504
258
|
return this;
|
|
505
259
|
}
|
|
506
|
-
|
|
507
|
-
/**
|
|
508
|
-
* Add a numeric filter (range comparison).
|
|
509
|
-
* @param {string} field - Field to filter on
|
|
510
|
-
* @param {">" | ">=" | "<" | "<="} operator - Comparison operator
|
|
511
|
-
* @param {number} value - Numeric threshold
|
|
512
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
513
|
-
* @returns {this}
|
|
514
|
-
*/
|
|
515
260
|
numeric(field, operator, value, boost = null) {
|
|
516
261
|
this._requireActiveArray();
|
|
517
262
|
this._requireBoostForBoostArray(boost);
|
|
518
263
|
this._active_array.push(new NumericFilter(field, operator, value, boost));
|
|
519
264
|
return this;
|
|
520
265
|
}
|
|
521
|
-
|
|
522
|
-
/**
|
|
523
|
-
* Add a date range filter.
|
|
524
|
-
* @param {string} field - Date field to filter on
|
|
525
|
-
* @param {string | null} [dateFrom=null] - Start date (ISO 8601)
|
|
526
|
-
* @param {string | null} [dateTo=null] - End date (ISO 8601)
|
|
527
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
528
|
-
* @returns {this}
|
|
529
|
-
*/
|
|
530
266
|
date(field, dateFrom = null, dateTo = null, boost = null) {
|
|
531
267
|
this._requireActiveArray();
|
|
532
268
|
this._requireBoostForBoostArray(boost);
|
|
533
269
|
this._active_array.push(new DateFilter(field, dateFrom, dateTo, boost));
|
|
534
270
|
return this;
|
|
535
271
|
}
|
|
536
|
-
|
|
537
|
-
/**
|
|
538
|
-
* Add a geo filter (distance from coordinates).
|
|
539
|
-
* @param {string} field - Geo point field
|
|
540
|
-
* @param {string[]} value - Coordinates, e.g. ["geo:40.7128,-74.0060"]
|
|
541
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
542
|
-
* @returns {this}
|
|
543
|
-
*/
|
|
544
272
|
geo(field, value, boost = null) {
|
|
545
273
|
this._requireActiveArray();
|
|
546
274
|
this._requireBoostForBoostArray(boost);
|
|
547
275
|
this._active_array.push(new GeoFilter(field, value, boost));
|
|
548
276
|
return this;
|
|
549
277
|
}
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Add a match filter (full-text keywords).
|
|
553
|
-
* @param {string} field - Text field to match against
|
|
554
|
-
* @param {string[]} value - Keywords to match
|
|
555
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
556
|
-
* @returns {this}
|
|
557
|
-
*/
|
|
558
278
|
match(field, value, boost = null) {
|
|
559
279
|
this._requireActiveArray();
|
|
560
280
|
this._requireBoostForBoostArray(boost);
|
|
561
281
|
this._active_array.push(new MatchFilter(field, value, boost));
|
|
562
282
|
return this;
|
|
563
283
|
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Add an is_null filter (field must be missing/null).
|
|
567
|
-
* @param {string} field - Field that must be empty
|
|
568
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
569
|
-
* @returns {this}
|
|
570
|
-
*/
|
|
571
284
|
isNull(field, boost = null) {
|
|
572
285
|
this._requireActiveArray();
|
|
573
286
|
this._requireBoostForBoostArray(boost);
|
|
574
287
|
this._active_array.push(new IsNullFilter(field, boost));
|
|
575
288
|
return this;
|
|
576
289
|
}
|
|
577
|
-
|
|
578
|
-
/**
|
|
579
|
-
* Add a not_null filter (field must exist and have a value).
|
|
580
|
-
* @param {string} field - Field that must exist
|
|
581
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
582
|
-
* @returns {this}
|
|
583
|
-
*/
|
|
584
290
|
notNull(field, boost = null) {
|
|
585
291
|
this._requireActiveArray();
|
|
586
292
|
this._requireBoostForBoostArray(boost);
|
|
587
293
|
this._active_array.push(new NotNullFilter(field, boost));
|
|
588
294
|
return this;
|
|
589
295
|
}
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
* Add a custom filter (raw Elasticsearch clause).
|
|
593
|
-
* @param {string} field - Ignored; use empty string if required by schema
|
|
594
|
-
* @param {Record<string, unknown>} value - Custom Elasticsearch query clause
|
|
595
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
596
|
-
* @returns {this}
|
|
597
|
-
*/
|
|
598
296
|
custom(field, value, boost = null) {
|
|
599
297
|
this._requireActiveArray();
|
|
600
298
|
this._requireBoostForBoostArray(boost);
|
|
601
299
|
this._active_array.push(new CustomFilter(field, value, boost));
|
|
602
300
|
return this;
|
|
603
301
|
}
|
|
604
|
-
|
|
605
|
-
/**
|
|
606
|
-
* Add a group_boost filter (hierarchical boosting from lookup index).
|
|
607
|
-
* @param {string} lookup_index - Lookup index name
|
|
608
|
-
* @param {string} field - Target field in the lookup index
|
|
609
|
-
* @param {string} value - Lookup document ID
|
|
610
|
-
* @param {string} group - Group path prefix (e.g. "label")
|
|
611
|
-
* @param {number | null} [min_boost=null] - Minimum boost
|
|
612
|
-
* @param {number | null} [max_boost=null] - Maximum boost
|
|
613
|
-
* @param {number | null} [n=null] - Number of groups
|
|
614
|
-
* @returns {this}
|
|
615
|
-
*/
|
|
616
302
|
groupBoost(lookup_index, field, value, group, min_boost = null, max_boost = null, n = null) {
|
|
617
303
|
this._requireActiveArray();
|
|
618
|
-
this._active_array.push(
|
|
619
|
-
new GroupBoostFilter(lookup_index, field, value, group, min_boost, max_boost, n)
|
|
620
|
-
);
|
|
304
|
+
this._active_array.push(new GroupBoostFilter(lookup_index, field, value, group, min_boost, max_boost, n));
|
|
621
305
|
return this;
|
|
622
306
|
}
|
|
623
|
-
|
|
624
|
-
/**
|
|
625
|
-
* Add a terms_lookup filter (match from another ES document).
|
|
626
|
-
* @param {string} lookup_index - Index to look up terms from
|
|
627
|
-
* @param {string} field - Target field in the current index
|
|
628
|
-
* @param {string} value - Document ID in lookup_index
|
|
629
|
-
* @param {string} path - JSON path in the lookup document
|
|
630
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
631
|
-
* @returns {this}
|
|
632
|
-
*/
|
|
633
307
|
termsLookup(lookup_index, field, value, path, boost = null) {
|
|
634
308
|
this._requireActiveArray();
|
|
635
309
|
this._requireBoostForBoostArray(boost);
|
|
636
|
-
this._active_array.push(
|
|
637
|
-
new TermsLookupFilter(lookup_index, field, value, path, boost)
|
|
638
|
-
);
|
|
310
|
+
this._active_array.push(new TermsLookupFilter(lookup_index, field, value, path, boost));
|
|
639
311
|
return this;
|
|
640
312
|
}
|
|
641
|
-
|
|
642
|
-
/**
|
|
643
|
-
* Add a console_account filter (match from console-accounts document).
|
|
644
|
-
* @param {string} field - Target field to match
|
|
645
|
-
* @param {string} value - Console account ID
|
|
646
|
-
* @param {string} path - JSON path in the account document
|
|
647
|
-
* @param {number | null} [boost=null] - Optional boost multiplier
|
|
648
|
-
* @returns {this}
|
|
649
|
-
*/
|
|
650
313
|
consoleAccount(field, value, path, boost = null) {
|
|
651
314
|
this._requireActiveArray();
|
|
652
315
|
this._requireBoostForBoostArray(boost);
|
|
653
316
|
this._active_array.push(new ConsoleAccountFilter(field, value, path, boost));
|
|
654
317
|
return this;
|
|
655
318
|
}
|
|
656
|
-
|
|
657
|
-
/**
|
|
658
|
-
* Log a string.
|
|
659
|
-
* @param {string} string
|
|
660
|
-
*/
|
|
661
319
|
log(string) {
|
|
662
320
|
this._log(string);
|
|
663
321
|
}
|
|
664
|
-
|
|
665
|
-
/**
|
|
666
|
-
* Show results.
|
|
667
|
-
* @param {*} results
|
|
668
|
-
*/
|
|
669
322
|
show(results) {
|
|
670
323
|
this._show(results);
|
|
671
324
|
}
|
|
672
|
-
|
|
673
325
|
}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
import { Filter } from './Filter.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Match field values against data from a console account document (index: console-accounts).
|
|
5
|
-
*/
|
|
6
2
|
export class ConsoleAccountFilter extends Filter {
|
|
7
|
-
/**
|
|
8
|
-
* @param {string} field - Target field to match (e.g. "user_id", "item_id")
|
|
9
|
-
* @param {string} value - Console account ID
|
|
10
|
-
* @param {string} path - JSON path in the account document (e.g. "include_user_ids", "exclude_item_ids")
|
|
11
|
-
* @param {number | null} [boost=null] - Optional boost multiplier (0.1–100)
|
|
12
|
-
*/
|
|
13
3
|
constructor(field, value, path, boost = null) {
|
|
14
4
|
super('console_account', field, boost);
|
|
15
5
|
this.value = value;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import { Filter } from './Filter.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Custom Elasticsearch query clause. field is ignored by the API but required by the schema.
|
|
5
|
-
*/
|
|
6
2
|
export class CustomFilter extends Filter {
|
|
7
|
-
/**
|
|
8
|
-
* @param {string} field - Ignored for custom filters; use empty string or placeholder if required
|
|
9
|
-
* @param {Record<string, unknown>} value - Custom Elasticsearch query clause
|
|
10
|
-
* @param {number | null} [boost=null] - Optional boost multiplier (0.1–100)
|
|
11
|
-
*/
|
|
12
3
|
constructor(field, value, boost = null) {
|
|
13
4
|
super('custom', field, boost);
|
|
14
5
|
this.value = value;
|