hlquery-node-client 1.0.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/.github/workflows/ci.yml +37 -0
- package/LICENSE +29 -0
- package/README.md +316 -0
- package/example.js +636 -0
- package/examples/basic_usage.js +35 -0
- package/examples/collections.js +40 -0
- package/examples/csv.js +39 -0
- package/examples/documents.js +54 -0
- package/examples/flush.js +128 -0
- package/examples/keys.js +58 -0
- package/examples/pdf.js +40 -0
- package/examples/search.js +101 -0
- package/examples/vector.js +465 -0
- package/index.js +39 -0
- package/lib/Aliases.js +48 -0
- package/lib/Client.js +623 -0
- package/lib/Collections.js +159 -0
- package/lib/Documents.js +244 -0
- package/lib/Exceptions.js +101 -0
- package/lib/Keys.js +85 -0
- package/lib/Overrides.js +53 -0
- package/lib/Request.js +147 -0
- package/lib/Response.js +54 -0
- package/lib/Search.js +350 -0
- package/lib/Stopwords.js +60 -0
- package/lib/Synonyms.js +85 -0
- package/lib/System.js +110 -0
- package/lib/conformance.js +74 -0
- package/package.json +42 -0
- package/test/offline-smoke.js +86 -0
- package/utils/Auth.js +34 -0
- package/utils/CSVParser.js +160 -0
- package/utils/Config.js +57 -0
- package/utils/PDFParser.js +196 -0
- package/utils/Validator.js +143 -0
- package/utils/ranker.js +51 -0
package/example.js
ADDED
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hlquery Node.js API Comprehensive Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the main features of the hlquery Node.js client:
|
|
5
|
+
* - Health checks
|
|
6
|
+
* - Authentication (with and without token)
|
|
7
|
+
* - Listing collections
|
|
8
|
+
* - Getting collection fields
|
|
9
|
+
* - Listing documents with pagination
|
|
10
|
+
* - Multiple search methods
|
|
11
|
+
* - Dynamic authentication
|
|
12
|
+
*
|
|
13
|
+
* Usage: node example.js [command] [token]
|
|
14
|
+
* Commands:
|
|
15
|
+
* cols - Run collections API examples
|
|
16
|
+
* docs - Run documents API examples
|
|
17
|
+
* open - List and open collections (interactive)
|
|
18
|
+
* status - Show server health and status information
|
|
19
|
+
* help - Show this help message
|
|
20
|
+
* all - Run all examples (default)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const Client = require('./lib/Client');
|
|
24
|
+
|
|
25
|
+
// Configuration
|
|
26
|
+
const baseUrl = process.env.HLQ_BASE_URL || process.env.HLQUERY_BASE_URL || 'http://localhost:9200';
|
|
27
|
+
|
|
28
|
+
// Parse command line arguments
|
|
29
|
+
let command = 'all';
|
|
30
|
+
let testToken = null;
|
|
31
|
+
let offset = 0;
|
|
32
|
+
let limit = 1000;
|
|
33
|
+
let collectionName = null;
|
|
34
|
+
|
|
35
|
+
if (process.argv.length > 2) {
|
|
36
|
+
const firstArg = process.argv[2];
|
|
37
|
+
if (['cols', 'docs', 'open', 'status', 'help', 'all'].includes(firstArg)) {
|
|
38
|
+
command = firstArg;
|
|
39
|
+
// Parse pagination for cols command: cols [offset] [limit] [token]
|
|
40
|
+
if (command === 'cols' && process.argv.length >= 4) {
|
|
41
|
+
const offsetArg = parseInt(process.argv[3]);
|
|
42
|
+
if (!isNaN(offsetArg)) {
|
|
43
|
+
offset = offsetArg;
|
|
44
|
+
if (process.argv.length >= 5) {
|
|
45
|
+
const limitArg = parseInt(process.argv[4]);
|
|
46
|
+
if (!isNaN(limitArg)) {
|
|
47
|
+
limit = limitArg;
|
|
48
|
+
testToken = process.argv[5] || null;
|
|
49
|
+
} else {
|
|
50
|
+
testToken = process.argv[4];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
testToken = process.argv[3];
|
|
55
|
+
}
|
|
56
|
+
} else if (command === 'docs' && process.argv.length >= 4) {
|
|
57
|
+
// For docs command: docs [collection_name] [token]
|
|
58
|
+
collectionName = process.argv[3];
|
|
59
|
+
testToken = process.argv[4] || null;
|
|
60
|
+
} else {
|
|
61
|
+
// Look for token in remaining args (skip numeric args)
|
|
62
|
+
for (let i = 3; i < process.argv.length; i++) {
|
|
63
|
+
const arg = parseInt(process.argv[i]);
|
|
64
|
+
if (isNaN(arg)) {
|
|
65
|
+
testToken = process.argv[i];
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// First arg is token, use 'all' command
|
|
72
|
+
testToken = firstArg;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Show help if requested
|
|
77
|
+
if (command === 'help') {
|
|
78
|
+
console.log('=== hlquery Node.js API Example ===\n');
|
|
79
|
+
console.log('Usage: node example.js [command] [args...] [token]\n');
|
|
80
|
+
console.log('Commands:');
|
|
81
|
+
console.log(' cols - List collections (with pagination)');
|
|
82
|
+
console.log(' Usage: cols [offset] [limit] [token]');
|
|
83
|
+
console.log(' Example: cols 0 200 (list first 200 collections)');
|
|
84
|
+
console.log(' docs - Run documents API examples');
|
|
85
|
+
console.log(' Usage: docs [collection_name] [token]');
|
|
86
|
+
console.log(' Example: docs my_collection');
|
|
87
|
+
console.log(' open - List and open collections (interactive)');
|
|
88
|
+
console.log(' status - Show server health and status information');
|
|
89
|
+
console.log(' help - Show this help message');
|
|
90
|
+
console.log(' all - Run all examples (default)\n');
|
|
91
|
+
console.log('Authentication:');
|
|
92
|
+
console.log(' Token is optional. Only provide if server requires authentication.');
|
|
93
|
+
console.log(' Example: node example.js cols 0 200 my_token');
|
|
94
|
+
console.log(' Example: node example.js docs my_collection my_token\n');
|
|
95
|
+
console.log('Examples:');
|
|
96
|
+
console.log(' node example.js');
|
|
97
|
+
console.log(' node example.js cols');
|
|
98
|
+
console.log(' node example.js cols 0 200');
|
|
99
|
+
console.log(' node example.js docs my_collection');
|
|
100
|
+
console.log(' node example.js status');
|
|
101
|
+
process.exit(0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log('=== hlquery Node.js API Example ===');
|
|
105
|
+
console.log(`Command: ${command}\n`);
|
|
106
|
+
|
|
107
|
+
// Helper function to print results
|
|
108
|
+
function printResult(title, response, printBody = true) {
|
|
109
|
+
console.log('='.repeat(70));
|
|
110
|
+
console.log(`TEST: ${title}`);
|
|
111
|
+
console.log('-'.repeat(70));
|
|
112
|
+
|
|
113
|
+
if (response) {
|
|
114
|
+
const status = response.getStatusCode();
|
|
115
|
+
const body = response.getBody();
|
|
116
|
+
const headers = response.getHeaders();
|
|
117
|
+
|
|
118
|
+
console.log(`Status Code: ${status}`);
|
|
119
|
+
|
|
120
|
+
if (printBody && body) {
|
|
121
|
+
console.log('Response Body:');
|
|
122
|
+
if (typeof body === 'object') {
|
|
123
|
+
console.log(JSON.stringify(body, null, 2));
|
|
124
|
+
} else {
|
|
125
|
+
console.log(body);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (status >= 200 && status < 300) {
|
|
130
|
+
console.log('✓ SUCCESS');
|
|
131
|
+
} else {
|
|
132
|
+
console.log('✗ FAILED');
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
console.log('Invalid response');
|
|
136
|
+
}
|
|
137
|
+
console.log('\n');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Helper to get first collection name
|
|
141
|
+
async function getFirstCollection(client) {
|
|
142
|
+
try {
|
|
143
|
+
const collections = await client.listCollections(0, 1);
|
|
144
|
+
if (collections.getStatusCode() === 200) {
|
|
145
|
+
const body = collections.getBody();
|
|
146
|
+
if (body.collections && body.collections.length > 0) {
|
|
147
|
+
const first = body.collections[0];
|
|
148
|
+
return typeof first === 'object' ? (first.name || first) : first;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} catch (e) {
|
|
152
|
+
// Ignore errors
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Main function
|
|
158
|
+
async function main() {
|
|
159
|
+
// Create client
|
|
160
|
+
const client = new Client(baseUrl);
|
|
161
|
+
|
|
162
|
+
// Optional: Set authentication token if provided
|
|
163
|
+
// Uncomment and set token if your server requires authentication:
|
|
164
|
+
// const authToken = 'your_token_here';
|
|
165
|
+
// client.setAuthToken(authToken, 'bearer');
|
|
166
|
+
|
|
167
|
+
if (testToken) {
|
|
168
|
+
client.setAuthToken(testToken, 'bearer');
|
|
169
|
+
console.log(`Using authentication token: ${testToken.substring(0, 8)}...\n`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ----------------------------------------------------------------====================================
|
|
173
|
+
// STATUS COMMAND
|
|
174
|
+
// ----------------------------------------------------------------====================================
|
|
175
|
+
if (command === 'status') {
|
|
176
|
+
console.log('\n' + '#'.repeat(70));
|
|
177
|
+
console.log('# SERVER STATUS');
|
|
178
|
+
console.log('#'.repeat(70) + '\n');
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
// GET /health
|
|
182
|
+
printResult('GET /health', await client.health());
|
|
183
|
+
|
|
184
|
+
// GET /stats
|
|
185
|
+
printResult('GET /stats', await client.stats());
|
|
186
|
+
|
|
187
|
+
// GET /etc (protocol codes)
|
|
188
|
+
const etc = await client.executeRequest('GET', '/etc');
|
|
189
|
+
printResult('GET /etc (Protocol Codes)', etc);
|
|
190
|
+
|
|
191
|
+
// GET /status
|
|
192
|
+
const status = await client.executeRequest('GET', '/status');
|
|
193
|
+
printResult('GET /status', status);
|
|
194
|
+
|
|
195
|
+
// GET / (Root Info) - show concise version
|
|
196
|
+
const info = await client.info();
|
|
197
|
+
console.log('='.repeat(70));
|
|
198
|
+
console.log('TEST: GET / (Root Info)');
|
|
199
|
+
console.log('-'.repeat(70));
|
|
200
|
+
if (info) {
|
|
201
|
+
const statusCode = info.getStatusCode();
|
|
202
|
+
const body = info.getBody();
|
|
203
|
+
console.log(`Status Code: ${statusCode}`);
|
|
204
|
+
if (statusCode >= 200 && statusCode < 300 && body && typeof body === 'object') {
|
|
205
|
+
console.log(`Name: ${body.name || 'N/A'}`);
|
|
206
|
+
console.log(`Version: ${body.version || 'N/A'}`);
|
|
207
|
+
console.log(`Description: ${body.description || 'N/A'}`);
|
|
208
|
+
console.log('✓ SUCCESS');
|
|
209
|
+
} else {
|
|
210
|
+
console.log('Response Body:');
|
|
211
|
+
console.log(JSON.stringify(body, null, 2));
|
|
212
|
+
console.log('✓ SUCCESS');
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
console.log('Invalid response');
|
|
216
|
+
}
|
|
217
|
+
console.log('\n');
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.log(`Error getting status: ${error.message}\n`);
|
|
220
|
+
}
|
|
221
|
+
process.exit(0);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ----------------------------------------------------------------====================================
|
|
225
|
+
// System APIs (only for 'all' command)
|
|
226
|
+
// ----------------------------------------------------------------====================================
|
|
227
|
+
if (command === 'all') {
|
|
228
|
+
console.log('\n' + '#'.repeat(70));
|
|
229
|
+
console.log('# System APIs');
|
|
230
|
+
console.log('#'.repeat(70) + '\n');
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
// GET /health
|
|
234
|
+
printResult('GET /health', await client.health());
|
|
235
|
+
|
|
236
|
+
// GET /stats
|
|
237
|
+
printResult('GET /stats', await client.stats());
|
|
238
|
+
|
|
239
|
+
// GET /etc (protocol codes)
|
|
240
|
+
const etc = await client.executeRequest('GET', '/etc');
|
|
241
|
+
printResult('GET /etc (Protocol Codes)', etc);
|
|
242
|
+
|
|
243
|
+
// GET /metrics (Prometheus-compatible)
|
|
244
|
+
const metrics = await client.executeRequest('GET', '/metrics');
|
|
245
|
+
printResult('GET /metrics', metrics);
|
|
246
|
+
|
|
247
|
+
// GET /status
|
|
248
|
+
const status = await client.executeRequest('GET', '/status');
|
|
249
|
+
printResult('GET /status', status);
|
|
250
|
+
|
|
251
|
+
// GET /
|
|
252
|
+
printResult('GET / (Root)', await client.info());
|
|
253
|
+
|
|
254
|
+
} catch (error) {
|
|
255
|
+
console.log(`Error in system APIs: ${error.message}\n`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// ----------------------------------------------------------------====================================
|
|
260
|
+
// COLLECTIONS API
|
|
261
|
+
// ----------------------------------------------------------------====================================
|
|
262
|
+
if (command === 'all' || command === 'cols' || command === 'open') {
|
|
263
|
+
console.log('\n' + '#'.repeat(70));
|
|
264
|
+
console.log('# COLLECTIONS API');
|
|
265
|
+
console.log('#'.repeat(70) + '\n');
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
// GET /collections with pagination
|
|
269
|
+
const collections = await client.listCollections(offset, limit);
|
|
270
|
+
|
|
271
|
+
if (command === 'cols') {
|
|
272
|
+
// Simple list display for cols command
|
|
273
|
+
if (collections.getStatusCode() === 200) {
|
|
274
|
+
const body = collections.getBody();
|
|
275
|
+
if (body.collections) {
|
|
276
|
+
const colsList = body.collections;
|
|
277
|
+
const total = colsList.length;
|
|
278
|
+
console.log(`Collections (showing ${total}, offset: ${offset}, limit: ${limit}):\n`);
|
|
279
|
+
colsList.forEach(col => {
|
|
280
|
+
const name = typeof col === 'object' ? (col.name || col) : col;
|
|
281
|
+
console.log(` ${name}`);
|
|
282
|
+
});
|
|
283
|
+
console.log();
|
|
284
|
+
} else {
|
|
285
|
+
console.log('No collections found.\n');
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
console.log(`Error: ${collections.getStatusCode()}\n`);
|
|
289
|
+
const body = collections.getBody();
|
|
290
|
+
if (body && body.message) {
|
|
291
|
+
console.log(`Message: ${body.message}\n`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
} else {
|
|
295
|
+
// Full display for 'all' and 'open' commands
|
|
296
|
+
printResult('GET /collections (List)', collections);
|
|
297
|
+
|
|
298
|
+
// Get first collection for other tests
|
|
299
|
+
const firstCollection = await getFirstCollection(client);
|
|
300
|
+
|
|
301
|
+
if (firstCollection && command === 'all') {
|
|
302
|
+
console.log(`Using collection: ${firstCollection}\n`);
|
|
303
|
+
|
|
304
|
+
// GET /collections/{name}
|
|
305
|
+
printResult(`GET /collections/${firstCollection}`, await client.getCollection(firstCollection));
|
|
306
|
+
|
|
307
|
+
// GET /collections/{name} (fields formatted)
|
|
308
|
+
printResult(`GET /collections/${firstCollection}/fields (formatted)`,
|
|
309
|
+
await client.getCollectionFields(firstCollection));
|
|
310
|
+
|
|
311
|
+
// Test creating a temporary collection
|
|
312
|
+
const testCollectionName = `test_collection_${Date.now()}`;
|
|
313
|
+
const testSchema = {
|
|
314
|
+
fields: [
|
|
315
|
+
{ name: 'title', type: 'string' },
|
|
316
|
+
{ name: 'content', type: 'string' },
|
|
317
|
+
{ name: 'embedding', type: 'float[]' }
|
|
318
|
+
]
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// POST /collections
|
|
322
|
+
const createResult = await client.collections().create(testCollectionName, testSchema);
|
|
323
|
+
printResult('POST /collections (Create)', createResult);
|
|
324
|
+
|
|
325
|
+
if (createResult.getStatusCode() === 200 || createResult.getStatusCode() === 201) {
|
|
326
|
+
// POST /collections/{name}/update
|
|
327
|
+
const updateSchema = {
|
|
328
|
+
fields: [
|
|
329
|
+
{ name: 'title', type: 'string' },
|
|
330
|
+
{ name: 'content', type: 'string' },
|
|
331
|
+
{ name: 'embedding', type: 'float[]' },
|
|
332
|
+
{ name: 'tags', type: 'string[]' }
|
|
333
|
+
]
|
|
334
|
+
};
|
|
335
|
+
const updateResult = await client.collections().update(testCollectionName, updateSchema);
|
|
336
|
+
printResult('POST /collections/{name}/update', updateResult);
|
|
337
|
+
|
|
338
|
+
// DELETE /collections/{name} (cleanup)
|
|
339
|
+
const deleteResult = await client.collections().delete(testCollectionName);
|
|
340
|
+
printResult('DELETE /collections/{name}', deleteResult);
|
|
341
|
+
}
|
|
342
|
+
} else if (!firstCollection) {
|
|
343
|
+
console.log('No collections found - skipping collection-specific tests\n');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// For 'open' command, list all collections
|
|
348
|
+
if (command === 'open') {
|
|
349
|
+
const collections = await client.listCollections(0, 1000);
|
|
350
|
+
if (collections.getStatusCode() === 200) {
|
|
351
|
+
const body = collections.getBody();
|
|
352
|
+
if (body.collections) {
|
|
353
|
+
console.log('\nAvailable Collections:');
|
|
354
|
+
console.log('-'.repeat(70));
|
|
355
|
+
body.collections.forEach(col => {
|
|
356
|
+
const name = typeof col === 'object' ? (col.name || col) : col;
|
|
357
|
+
console.log(` ${name}`);
|
|
358
|
+
});
|
|
359
|
+
console.log();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.log(`Error in collections API: ${error.message}\n`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ----------------------------------------------------------------====================================
|
|
370
|
+
// DOCUMENTS API
|
|
371
|
+
// ----------------------------------------------------------------====================================
|
|
372
|
+
if (command === 'all' || command === 'docs' || command === 'open') {
|
|
373
|
+
console.log('\n' + '#'.repeat(70));
|
|
374
|
+
console.log('# DOCUMENTS API');
|
|
375
|
+
console.log('#'.repeat(70) + '\n');
|
|
376
|
+
|
|
377
|
+
// Use provided collection name or get first collection
|
|
378
|
+
const testCollection = collectionName || await getFirstCollection(client);
|
|
379
|
+
if (!testCollection) {
|
|
380
|
+
if (command === 'docs' && !collectionName) {
|
|
381
|
+
console.log('Error: No collection name provided and no collections found.');
|
|
382
|
+
console.log('Usage: node example.js docs [collection_name] [token]\n');
|
|
383
|
+
} else {
|
|
384
|
+
console.log('No collections available - skipping document tests\n');
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
if (command === 'docs' && collectionName) {
|
|
388
|
+
console.log(`Using collection: ${testCollection}\n`);
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
// GET /collections/{name}/documents
|
|
392
|
+
const documents = await client.listDocuments(testCollection, { offset: 0, limit: limit });
|
|
393
|
+
|
|
394
|
+
if (command === 'docs') {
|
|
395
|
+
// Simple list display for docs command
|
|
396
|
+
if (documents.getStatusCode() === 200) {
|
|
397
|
+
const body = documents.getBody();
|
|
398
|
+
if (body.documents) {
|
|
399
|
+
const docsList = body.documents;
|
|
400
|
+
const total = docsList.length;
|
|
401
|
+
console.log(`Documents in '${testCollection}' (showing ${total}, limit: ${limit}):\n`);
|
|
402
|
+
docsList.forEach(doc => {
|
|
403
|
+
const docId = typeof doc === 'object' ? (doc.id || doc) : doc;
|
|
404
|
+
console.log(` ${docId}`);
|
|
405
|
+
});
|
|
406
|
+
console.log();
|
|
407
|
+
} else {
|
|
408
|
+
console.log('No documents found.\n');
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
console.log(`Error: ${documents.getStatusCode()}\n`);
|
|
412
|
+
const body = documents.getBody();
|
|
413
|
+
if (body && body.message) {
|
|
414
|
+
console.log(`Message: ${body.message}\n`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
// Full display for 'all' command
|
|
419
|
+
printResult('GET /collections/{name}/documents (List)', documents);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Get a document ID if available (for 'all' command)
|
|
423
|
+
let testDocId = null;
|
|
424
|
+
if (command === 'all') {
|
|
425
|
+
const documents = await client.listDocuments(testCollection, { offset: 0, limit: 1 });
|
|
426
|
+
if (documents.getStatusCode() === 200) {
|
|
427
|
+
const body = documents.getBody();
|
|
428
|
+
if (body.documents && body.documents.length > 0) {
|
|
429
|
+
const doc = body.documents[0];
|
|
430
|
+
testDocId = typeof doc === 'object' ? (doc.id || null) : null;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (testDocId) {
|
|
436
|
+
// GET /collections/{name}/documents/{id}
|
|
437
|
+
printResult(`GET /collections/${testCollection}/documents/${testDocId}`,
|
|
438
|
+
await client.getDocument(testCollection, testDocId));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// POST /collections/{name}/documents (Add)
|
|
442
|
+
const newDoc = {
|
|
443
|
+
id: `test_doc_${Date.now()}`,
|
|
444
|
+
title: 'Test Document',
|
|
445
|
+
content: 'This is a test document for API testing',
|
|
446
|
+
embedding: [0.1, 0.2, 0.3, 0.4, 0.5] // Sample vector
|
|
447
|
+
};
|
|
448
|
+
const addResult = await client.documents().add(testCollection, newDoc);
|
|
449
|
+
printResult('POST /collections/{name}/documents (Add)', addResult);
|
|
450
|
+
|
|
451
|
+
if (addResult.getStatusCode() === 200 || addResult.getStatusCode() === 201) {
|
|
452
|
+
const addedDocId = newDoc.id;
|
|
453
|
+
|
|
454
|
+
// PUT /collections/{name}/documents/{id}
|
|
455
|
+
const updatedDoc = {
|
|
456
|
+
title: 'Updated Test Document',
|
|
457
|
+
content: 'This document has been updated'
|
|
458
|
+
};
|
|
459
|
+
const updateResult = await client.documents().update(testCollection, addedDocId, updatedDoc);
|
|
460
|
+
printResult('PUT /collections/{name}/documents/{id} (Update)', updateResult);
|
|
461
|
+
|
|
462
|
+
// POST /collections/{name}/documents/import
|
|
463
|
+
const bulkDocs = [
|
|
464
|
+
{ id: 'bulk_1', title: 'Bulk Doc 1', content: 'Content 1' },
|
|
465
|
+
{ id: 'bulk_2', title: 'Bulk Doc 2', content: 'Content 2' },
|
|
466
|
+
{ id: 'bulk_3', title: 'Bulk Doc 3', content: 'Content 3' }
|
|
467
|
+
];
|
|
468
|
+
const importResult = await client.documents().import(testCollection, bulkDocs);
|
|
469
|
+
printResult('POST /collections/{name}/documents/import (Bulk Import)', importResult);
|
|
470
|
+
|
|
471
|
+
// DELETE /collections/{name}/documents/{id}
|
|
472
|
+
const deleteResult = await client.documents().delete(testCollection, addedDocId);
|
|
473
|
+
printResult('DELETE /collections/{name}/documents/{id}', deleteResult);
|
|
474
|
+
|
|
475
|
+
// DELETE /collections/{name}/documents (by filter)
|
|
476
|
+
const deleteByFilterResult = await client.documents().deleteByFilter(testCollection, 'title:Bulk*');
|
|
477
|
+
printResult('DELETE /collections/{name}/documents (by filter)', deleteByFilterResult);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
} catch (error) {
|
|
481
|
+
console.log(`Error in documents API: ${error.message}\n`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// ----------------------------------------------------------------====================================
|
|
487
|
+
// SEARCH API (only for 'all' command)
|
|
488
|
+
// ----------------------------------------------------------------====================================
|
|
489
|
+
if (command === 'all') {
|
|
490
|
+
console.log('\n' + '#'.repeat(70));
|
|
491
|
+
console.log('# SEARCH API');
|
|
492
|
+
console.log('#'.repeat(70) + '\n');
|
|
493
|
+
|
|
494
|
+
const searchCollection = await getFirstCollection(client);
|
|
495
|
+
if (!searchCollection) {
|
|
496
|
+
console.log('No collections available - skipping search tests\n');
|
|
497
|
+
} else {
|
|
498
|
+
try {
|
|
499
|
+
// GET/POST /collections/{name}/documents/search (Regular search)
|
|
500
|
+
const searchParams = {
|
|
501
|
+
q: 'test',
|
|
502
|
+
query_by: 'title,content',
|
|
503
|
+
limit: 5
|
|
504
|
+
};
|
|
505
|
+
printResult('GET /collections/{name}/documents/search (Regular Search)',
|
|
506
|
+
await client.search(searchCollection, searchParams));
|
|
507
|
+
|
|
508
|
+
// Search with sorting examples
|
|
509
|
+
console.log('\n--- Sorting Examples ---\n');
|
|
510
|
+
|
|
511
|
+
// Sort by relevance (default)
|
|
512
|
+
const searchRelevance = {
|
|
513
|
+
q: 'test',
|
|
514
|
+
query_by: 'title,content',
|
|
515
|
+
sort_by: '_text_match:desc',
|
|
516
|
+
limit: 5
|
|
517
|
+
};
|
|
518
|
+
printResult('Search sorted by Relevance (Best Match)',
|
|
519
|
+
await client.search(searchCollection, searchRelevance));
|
|
520
|
+
|
|
521
|
+
// Sort by title alphabetically
|
|
522
|
+
const searchTitle = {
|
|
523
|
+
q: 'test',
|
|
524
|
+
query_by: 'title,content',
|
|
525
|
+
sort_by: 'title:asc',
|
|
526
|
+
limit: 5
|
|
527
|
+
};
|
|
528
|
+
printResult('Search sorted by Title (A-Z)',
|
|
529
|
+
await client.search(searchCollection, searchTitle));
|
|
530
|
+
|
|
531
|
+
// Search with highlighting
|
|
532
|
+
console.log('\n--- Highlighting Examples ---\n');
|
|
533
|
+
const searchHighlight = {
|
|
534
|
+
q: 'test',
|
|
535
|
+
query_by: 'title,content',
|
|
536
|
+
highlight: true,
|
|
537
|
+
highlight_fields: ['title', 'content'],
|
|
538
|
+
limit: 5
|
|
539
|
+
};
|
|
540
|
+
printResult('Search with Highlighting',
|
|
541
|
+
await client.search(searchCollection, searchHighlight));
|
|
542
|
+
|
|
543
|
+
// Sort by document ID
|
|
544
|
+
const searchId = {
|
|
545
|
+
q: 'test',
|
|
546
|
+
query_by: 'title,content',
|
|
547
|
+
sort_by: 'id:asc',
|
|
548
|
+
limit: 5
|
|
549
|
+
};
|
|
550
|
+
printResult('Search sorted by Document ID (A-Z)',
|
|
551
|
+
await client.search(searchCollection, searchId));
|
|
552
|
+
|
|
553
|
+
// Sort by date (if available)
|
|
554
|
+
const searchDate = {
|
|
555
|
+
q: 'test',
|
|
556
|
+
query_by: 'title,content',
|
|
557
|
+
sort_by: 'created_at:desc',
|
|
558
|
+
limit: 5
|
|
559
|
+
};
|
|
560
|
+
printResult('Search sorted by Date (Newest First)',
|
|
561
|
+
await client.search(searchCollection, searchDate));
|
|
562
|
+
|
|
563
|
+
// POST /collections/{name}/vector_search (Vector search body)
|
|
564
|
+
const vectorQuery = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]; // Sample 10D vector
|
|
565
|
+
const vectorParams = {
|
|
566
|
+
body: {
|
|
567
|
+
vector: vectorQuery,
|
|
568
|
+
field_name: 'embedding',
|
|
569
|
+
topk: 5,
|
|
570
|
+
threshold: 0.0,
|
|
571
|
+
normalize: true,
|
|
572
|
+
include_vector: false
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
printResult('POST /collections/{name}/vector_search (Vector Search)',
|
|
576
|
+
await client.vectorSearch(searchCollection, vectorParams));
|
|
577
|
+
|
|
578
|
+
// POST /multi_search
|
|
579
|
+
const multiSearchParams = {
|
|
580
|
+
searches: [
|
|
581
|
+
{
|
|
582
|
+
collection: searchCollection,
|
|
583
|
+
q: 'test',
|
|
584
|
+
query_by: 'title'
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
collection: searchCollection,
|
|
588
|
+
q: 'document',
|
|
589
|
+
query_by: 'content'
|
|
590
|
+
}
|
|
591
|
+
]
|
|
592
|
+
};
|
|
593
|
+
printResult('POST /multi_search',
|
|
594
|
+
await client.searchApi().multiSearch(multiSearchParams.searches));
|
|
595
|
+
|
|
596
|
+
} catch (error) {
|
|
597
|
+
console.log(`Error in search API: ${error.message}\n`);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// ----------------------------------------------------------------====================================
|
|
603
|
+
// SUMMARY (only show for 'all' command)
|
|
604
|
+
// ----------------------------------------------------------------====================================
|
|
605
|
+
if (command === 'all') {
|
|
606
|
+
console.log('\n' + '#'.repeat(70));
|
|
607
|
+
console.log('# TESTING COMPLETE');
|
|
608
|
+
console.log('#'.repeat(70) + '\n');
|
|
609
|
+
|
|
610
|
+
console.log('Routes have been tested. Check the output above for results.');
|
|
611
|
+
console.log('Note: Some tests may fail if:');
|
|
612
|
+
console.log(' - Authentication is required but no token was provided');
|
|
613
|
+
console.log(' - Collections don\'t exist');
|
|
614
|
+
console.log(' - Required data is missing');
|
|
615
|
+
console.log('\n');
|
|
616
|
+
console.log('Usage: node example.js [command] [args...] [token]');
|
|
617
|
+
console.log(' Commands:');
|
|
618
|
+
console.log(' cols - List collections (with pagination)');
|
|
619
|
+
console.log(' Usage: cols [offset] [limit] [token]');
|
|
620
|
+
console.log(' Example: cols 0 200');
|
|
621
|
+
console.log(' docs - Run documents API examples');
|
|
622
|
+
console.log(' Usage: docs [collection_name] [token]');
|
|
623
|
+
console.log(' Example: docs my_collection');
|
|
624
|
+
console.log(' open - List and open collections');
|
|
625
|
+
console.log(' status - Show server health and status information');
|
|
626
|
+
console.log(' help - Show help message');
|
|
627
|
+
console.log(' all - Run all examples (default)');
|
|
628
|
+
console.log('\n');
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Run main function
|
|
633
|
+
main().catch(error => {
|
|
634
|
+
console.error('Fatal error:', error);
|
|
635
|
+
process.exit(1);
|
|
636
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Usage Examples
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates basic operations with the hlquery Node.js client
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Client = require('../lib/Client');
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
// Initialize client
|
|
11
|
+
const client = new Client('http://localhost:9200');
|
|
12
|
+
|
|
13
|
+
// Health check
|
|
14
|
+
const health = await client.health();
|
|
15
|
+
console.log('Health Status:', health.getStatusCode());
|
|
16
|
+
console.log('Health Body:', health.getBody());
|
|
17
|
+
|
|
18
|
+
// List collections
|
|
19
|
+
const collections = await client.listCollections(0, 10);
|
|
20
|
+
if (collections.isSuccess()) {
|
|
21
|
+
const body = collections.getBody();
|
|
22
|
+
console.log(`Found ${body.collections ? body.collections.length : 0} collections`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// With authentication
|
|
26
|
+
const authenticatedClient = new Client('http://localhost:9200', {
|
|
27
|
+
token: 'your_token_here',
|
|
28
|
+
auth_method: 'bearer'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Or set token dynamically
|
|
32
|
+
client.setAuthToken('your_token_here', 'bearer');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
main().catch(console.error);
|