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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collections Examples
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates collection management operations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Client = require('../lib/Client');
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
const client = new Client('http://localhost:9200');
|
|
11
|
+
|
|
12
|
+
// List collections
|
|
13
|
+
const collections = await client.collections().list(0, 10);
|
|
14
|
+
console.log('Collections:', collections.getBody());
|
|
15
|
+
|
|
16
|
+
// Get collection
|
|
17
|
+
const collection = await client.collections().get('my_collection');
|
|
18
|
+
console.log('Collection details:', collection.getBody());
|
|
19
|
+
|
|
20
|
+
// Create collection
|
|
21
|
+
const schema = {
|
|
22
|
+
fields: [
|
|
23
|
+
{ name: 'title', type: 'string' },
|
|
24
|
+
{ name: 'content', type: 'string' },
|
|
25
|
+
{ name: 'embedding', type: 'float[]' }
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
const createResult = await client.collections().create('new_collection', schema);
|
|
29
|
+
console.log('Create result:', createResult.getBody());
|
|
30
|
+
|
|
31
|
+
// Get formatted fields
|
|
32
|
+
const fields = await client.collections().getFields('my_collection');
|
|
33
|
+
console.log('Formatted fields:', fields.getBody());
|
|
34
|
+
|
|
35
|
+
// Delete collection
|
|
36
|
+
const deleteResult = await client.collections().delete('collection_name');
|
|
37
|
+
console.log('Delete result:', deleteResult.getBody());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
main().catch(console.error);
|
package/examples/csv.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV Parsing Example
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* node examples/csv.js <collection> <csv-path> [token]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const Client = require('../lib/Client');
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
const [, , collectionName, csvPath, token] = process.argv;
|
|
13
|
+
|
|
14
|
+
if (!collectionName || !csvPath) {
|
|
15
|
+
console.error('Usage: node examples/csv.js <collection> <csv-path> [token]');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const client = new Client('http://localhost:9200');
|
|
20
|
+
|
|
21
|
+
if (token) {
|
|
22
|
+
client.setAuthToken(token, 'bearer');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const response = await client.documents().addCSV(collectionName, csvPath, {
|
|
26
|
+
document: {
|
|
27
|
+
source_type: 'csv',
|
|
28
|
+
source_path: path.resolve(csvPath)
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(`Status: ${response.getStatusCode()}`);
|
|
33
|
+
console.log(JSON.stringify(response.getBody(), null, 2));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
main().catch((error) => {
|
|
37
|
+
console.error(error.message);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Documents Examples
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates document CRUD operations
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Client = require('../lib/Client');
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
const client = new Client('http://localhost:9200');
|
|
11
|
+
|
|
12
|
+
// List documents
|
|
13
|
+
const docs = await client.documents().list('collection', {
|
|
14
|
+
offset: 0,
|
|
15
|
+
limit: 10
|
|
16
|
+
});
|
|
17
|
+
console.log('Documents:', docs.getBody());
|
|
18
|
+
|
|
19
|
+
// Get document
|
|
20
|
+
const doc = await client.documents().get('collection', 'doc_id');
|
|
21
|
+
console.log('Document:', doc.getBody());
|
|
22
|
+
|
|
23
|
+
// Add document
|
|
24
|
+
const newDoc = {
|
|
25
|
+
id: 'doc_1',
|
|
26
|
+
title: 'New Document',
|
|
27
|
+
content: 'Document content'
|
|
28
|
+
};
|
|
29
|
+
const addResult = await client.documents().add('collection', newDoc);
|
|
30
|
+
console.log('Add result:', addResult.getBody());
|
|
31
|
+
|
|
32
|
+
// Update document
|
|
33
|
+
const updatedDoc = {
|
|
34
|
+
title: 'Updated Document',
|
|
35
|
+
content: 'Updated content'
|
|
36
|
+
};
|
|
37
|
+
const updateResult = await client.documents().update('collection', 'doc_id', updatedDoc);
|
|
38
|
+
console.log('Update result:', updateResult.getBody());
|
|
39
|
+
|
|
40
|
+
// Delete document
|
|
41
|
+
const deleteResult = await client.documents().delete('collection', 'doc_id');
|
|
42
|
+
console.log('Delete result:', deleteResult.getBody());
|
|
43
|
+
|
|
44
|
+
// Bulk import
|
|
45
|
+
const bulkDocs = [
|
|
46
|
+
{ id: 'doc1', title: 'Doc 1' },
|
|
47
|
+
{ id: 'doc2', title: 'Doc 2' },
|
|
48
|
+
{ id: 'doc3', title: 'Doc 3' }
|
|
49
|
+
];
|
|
50
|
+
const importResult = await client.documents().import('collection', bulkDocs);
|
|
51
|
+
console.log('Import result:', importResult.getBody());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flush Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the flush operation:
|
|
5
|
+
* 1. Create a fake collection
|
|
6
|
+
* 2. Create a fake document
|
|
7
|
+
* 3. Check collection count
|
|
8
|
+
* 4. Flush all data
|
|
9
|
+
* 5. Re-check collection count (should be 0)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const Client = require('../lib/Client');
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
const client = new Client('http://localhost:9200');
|
|
16
|
+
|
|
17
|
+
console.log('='.repeat(70));
|
|
18
|
+
console.log('FLUSH EXAMPLE');
|
|
19
|
+
console.log('='.repeat(70));
|
|
20
|
+
console.log();
|
|
21
|
+
|
|
22
|
+
// Step 1: Create a fake collection
|
|
23
|
+
console.log('Step 1: Creating a fake collection...');
|
|
24
|
+
const collection_name = 'flush_test_collection_' + Date.now();
|
|
25
|
+
|
|
26
|
+
const schema = {
|
|
27
|
+
fields: [
|
|
28
|
+
{ name: 'title', type: 'string' },
|
|
29
|
+
{ name: 'content', type: 'string' },
|
|
30
|
+
{ name: 'value', type: 'int' }
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const create_result = await client.collections().create(collection_name, schema);
|
|
35
|
+
if (create_result.isSuccess()) {
|
|
36
|
+
console.log(` ✓ Collection '${collection_name}' created successfully`);
|
|
37
|
+
} else {
|
|
38
|
+
console.log(` ✗ Failed to create collection: ${create_result.getStatusCode()}`);
|
|
39
|
+
console.log(` Error: ${JSON.stringify(create_result.getBody(), null, 2)}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log();
|
|
44
|
+
|
|
45
|
+
// Step 2: Create a fake document
|
|
46
|
+
console.log('Step 2: Creating a fake document...');
|
|
47
|
+
const doc = {
|
|
48
|
+
id: 'flush_test_doc_' + Date.now(),
|
|
49
|
+
title: 'Flush Test Document',
|
|
50
|
+
content: 'This is a test document for flush example',
|
|
51
|
+
value: 42
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const add_result = await client.documents().add(collection_name, doc);
|
|
55
|
+
if (add_result.isSuccess()) {
|
|
56
|
+
console.log(` ✓ Document '${doc.id}' added successfully`);
|
|
57
|
+
} else {
|
|
58
|
+
console.log(` ✗ Failed to add document: ${add_result.getStatusCode()}`);
|
|
59
|
+
console.log(` Error: ${JSON.stringify(add_result.getBody(), null, 2)}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log();
|
|
63
|
+
|
|
64
|
+
// Step 3: Check collection count before flush
|
|
65
|
+
console.log('Step 3: Checking collection count before flush...');
|
|
66
|
+
const collections_before = await client.listCollections(0, 1000);
|
|
67
|
+
let count_before = 0;
|
|
68
|
+
if (collections_before.isSuccess()) {
|
|
69
|
+
const body = collections_before.getBody();
|
|
70
|
+
const collections_list = body.collections || [];
|
|
71
|
+
count_before = collections_list.length;
|
|
72
|
+
console.log(` Collections before flush: ${count_before}`);
|
|
73
|
+
if (count_before === 0) {
|
|
74
|
+
console.log(' ⚠ Warning: No collections found before flush');
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
console.log(` ✗ Failed to list collections: ${collections_before.getStatusCode()}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log();
|
|
81
|
+
|
|
82
|
+
// Step 4: Flush all data
|
|
83
|
+
console.log('Step 4: Flushing all data...');
|
|
84
|
+
const flush_result = await client.flush();
|
|
85
|
+
if (flush_result.isSuccess()) {
|
|
86
|
+
const body = flush_result.getBody();
|
|
87
|
+
const collections_deleted = body.collections_deleted || 0;
|
|
88
|
+
console.log(' ✓ Flush completed successfully');
|
|
89
|
+
console.log(` Collections deleted: ${collections_deleted}`);
|
|
90
|
+
console.log(` Message: ${body.message || 'N/A'}`);
|
|
91
|
+
} else {
|
|
92
|
+
console.log(` ✗ Flush failed: ${flush_result.getStatusCode()}`);
|
|
93
|
+
console.log(` Error: ${JSON.stringify(flush_result.getBody(), null, 2)}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log();
|
|
98
|
+
|
|
99
|
+
// Step 5: Re-check collection count after flush
|
|
100
|
+
console.log('Step 5: Checking collection count after flush...');
|
|
101
|
+
const collections_after = await client.listCollections(0, 1000);
|
|
102
|
+
let count_after = -1;
|
|
103
|
+
if (collections_after.isSuccess()) {
|
|
104
|
+
const body = collections_after.getBody();
|
|
105
|
+
const collections_list = body.collections || [];
|
|
106
|
+
count_after = collections_list.length;
|
|
107
|
+
console.log(` Collections after flush: ${count_after}`);
|
|
108
|
+
|
|
109
|
+
if (count_after === 0) {
|
|
110
|
+
console.log(' ✓ SUCCESS: All collections have been flushed');
|
|
111
|
+
} else {
|
|
112
|
+
console.log(` ⚠ Warning: Expected 0 collections, but found ${count_after}`);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
console.log(` ✗ Failed to list collections: ${collections_after.getStatusCode()}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log();
|
|
119
|
+
console.log('='.repeat(70));
|
|
120
|
+
console.log('FLUSH EXAMPLE COMPLETED');
|
|
121
|
+
console.log('='.repeat(70));
|
|
122
|
+
console.log('Summary:');
|
|
123
|
+
console.log(` Collections before flush: ${count_before}`);
|
|
124
|
+
console.log(` Collections after flush: ${count_after}`);
|
|
125
|
+
console.log();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
main().catch(console.error);
|
package/examples/keys.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hlquery Node.js Example - API Keys Management
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to create, list, and delete API keys.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Client = require('../index');
|
|
8
|
+
|
|
9
|
+
// Replace with your hlquery master admin token
|
|
10
|
+
const ADMIN_TOKEN = 'your_admin_token_here';
|
|
11
|
+
const BASE_URL = 'http://localhost:9200';
|
|
12
|
+
|
|
13
|
+
async function run() {
|
|
14
|
+
try {
|
|
15
|
+
const client = new Client(BASE_URL);
|
|
16
|
+
client.setAuthToken(ADMIN_TOKEN);
|
|
17
|
+
|
|
18
|
+
console.log('1. Creating a scoped search key for "products" collection...');
|
|
19
|
+
const createResp = await client.keys().create({
|
|
20
|
+
description: 'Public search key for products',
|
|
21
|
+
collections: ['products'],
|
|
22
|
+
actions: ['search'],
|
|
23
|
+
embedded_filters: 'is_public:=true'
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (createResp.getStatusCode() === 201) {
|
|
27
|
+
const newKey = createResp.getBody().key;
|
|
28
|
+
const keyId = createResp.getBody().id;
|
|
29
|
+
console.log(` ✓ Key created: ${newKey}`);
|
|
30
|
+
console.log(` ✓ Key ID: ${keyId}`);
|
|
31
|
+
|
|
32
|
+
console.log('\n2. Listing all API keys...');
|
|
33
|
+
const listResp = await client.keys().list();
|
|
34
|
+
console.log(` ✓ Found ${listResp.getBody().keys.length} keys`);
|
|
35
|
+
|
|
36
|
+
console.log('\n3. Getting key details...');
|
|
37
|
+
const getResp = await client.keys().get(keyId);
|
|
38
|
+
console.log(` ✓ Key description: ${getResp.getBody().description}`);
|
|
39
|
+
|
|
40
|
+
console.log('\n4. Updating key permissions...');
|
|
41
|
+
await client.keys().update(keyId, {
|
|
42
|
+
actions: ['search', 'create']
|
|
43
|
+
});
|
|
44
|
+
console.log(' ✓ Permissions updated');
|
|
45
|
+
|
|
46
|
+
console.log('\n5. Deleting the key...');
|
|
47
|
+
await client.keys().delete(keyId);
|
|
48
|
+
console.log(' ✓ Key deleted');
|
|
49
|
+
} else {
|
|
50
|
+
console.error(' ✗ Failed to create key:', createResp.getBody());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('Error:', error.message);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
run();
|
package/examples/pdf.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDF Parsing Example
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npm install
|
|
6
|
+
* node examples/pdf.js <collection> <pdf-path> [token]
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const Client = require('../lib/Client');
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
const [, , collectionName, pdfPath, token] = process.argv;
|
|
14
|
+
|
|
15
|
+
if (!collectionName || !pdfPath) {
|
|
16
|
+
console.error('Usage: node examples/pdf.js <collection> <pdf-path> [token]');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const client = new Client('http://localhost:9200');
|
|
21
|
+
|
|
22
|
+
if (token) {
|
|
23
|
+
client.setAuthToken(token, 'bearer');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const response = await client.documents().addPDF(collectionName, pdfPath, {
|
|
27
|
+
document: {
|
|
28
|
+
source_type: 'pdf',
|
|
29
|
+
source_path: path.resolve(pdfPath)
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(`Status: ${response.getStatusCode()}`);
|
|
34
|
+
console.log(JSON.stringify(response.getBody(), null, 2));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
main().catch((error) => {
|
|
38
|
+
console.error(error.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Examples
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates various search patterns with the hlquery Node.js client
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const Client = require('../lib/Client');
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
const client = new Client('http://localhost:9200');
|
|
11
|
+
const search = client.searchApi();
|
|
12
|
+
|
|
13
|
+
// Simple search. The SDK uses the canonical /collections/{name}/search route.
|
|
14
|
+
const results = await search.search('collection_name', {
|
|
15
|
+
q: 'search query',
|
|
16
|
+
query_by: 'title,content',
|
|
17
|
+
limit: 10
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Search with filters
|
|
21
|
+
const filteredResults = await client.search('collection_name', {
|
|
22
|
+
q: 'query',
|
|
23
|
+
query_by: 'title',
|
|
24
|
+
filter_by: 'category:electronics',
|
|
25
|
+
sort_by: 'price:asc',
|
|
26
|
+
limit: 20
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Supported query semantics
|
|
30
|
+
// Field-specific search
|
|
31
|
+
const fieldResults = await client.search('collection_name', {
|
|
32
|
+
q: 'title:laptop',
|
|
33
|
+
query_by: 'title,content',
|
|
34
|
+
limit: 10
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Boolean OR query
|
|
38
|
+
const orResults = await client.search('collection_name', {
|
|
39
|
+
q: 'title:laptop OR title:notebook',
|
|
40
|
+
query_by: 'title,content',
|
|
41
|
+
limit: 10
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Boolean NOT query
|
|
45
|
+
const notResults = await client.search('collection_name', {
|
|
46
|
+
q: 'title:laptop NOT title:refurbished',
|
|
47
|
+
query_by: 'title,content',
|
|
48
|
+
limit: 10
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Phrase search
|
|
52
|
+
const phraseResults = await client.search('collection_name', {
|
|
53
|
+
q: '"wireless keyboard"',
|
|
54
|
+
query_by: 'title',
|
|
55
|
+
limit: 10
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Wildcard search
|
|
59
|
+
const wildcardResults = await client.search('collection_name', {
|
|
60
|
+
q: 'laptop*',
|
|
61
|
+
query_by: 'title,content',
|
|
62
|
+
limit: 10
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// query_by restriction
|
|
66
|
+
const restrictedResults = await client.search('collection_name', {
|
|
67
|
+
q: 'laptop',
|
|
68
|
+
query_by: 'title',
|
|
69
|
+
limit: 10
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Filter operators belong in filter_by
|
|
73
|
+
const combinedResults = await client.search('collection_name', {
|
|
74
|
+
q: '*',
|
|
75
|
+
query_by: 'title,content',
|
|
76
|
+
filter_by: 'price:>100&&category:electronics',
|
|
77
|
+
limit: 10
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Vector search
|
|
81
|
+
const vectorResults = await client.vectorSearch('collection_name', {
|
|
82
|
+
body: {
|
|
83
|
+
vector: [0.1, 0.2, 0.3, 0.4, 0.5],
|
|
84
|
+
field_name: 'embedding',
|
|
85
|
+
topk: 10,
|
|
86
|
+
threshold: 0.5,
|
|
87
|
+
include_distance: true,
|
|
88
|
+
query_params: { ef: 64, nprobe: 4, is_linear: true }
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Multi-search
|
|
93
|
+
const multiResults = await search.multiSearch([
|
|
94
|
+
{ collection: 'col1', q: 'query1', query_by: 'title' },
|
|
95
|
+
{ collection: 'col2', q: 'query2', query_by: 'content' }
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
console.log('Search results:', results.getBody());
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
main().catch(console.error);
|