@oxlayer/capabilities-adapters-search-quickwit
v0.1.4
Published
Quickwit search adapter for @oxlayer/capabilities
Readme
@oxlayer/capabilities-adapters-search-quickwit
Quickwit search adapter for @oxlayer/capabilities. Provides a simplified interface for searching log analytics and observability data with Quickwit.
Features
- Simplified Quickwit search client
- Full-text search with fuzzy matching
- Document retrieval by ID
- Index management (list, delete, get info)
- Aggregation support
- Snippet extraction
- Sorting and pagination
- Health check
- API key authentication
Installation
bun add @oxlayer/capabilities-adapters-search-quickwitUsage
Basic Setup
import { createQuickwitSearchClient } from '@oxlayer/capabilities-adapters-search-quickwit';
const search = createQuickwitSearchClient({
url: 'http://localhost:7280',
indexId: 'logs',
});
// Search documents
const results = await search.search({
query: 'error',
maxHits: 10,
});
console.log(results.hits);
console.log(results.aggregations);Environment Variables
import { createDefaultQuickwitSearchClient } from '@oxlayer/capabilities-adapters-search-quickwit';
const search = createDefaultQuickwitSearchClient();
// Uses environment variables:
// QUICKWIT_URL=http://localhost:7280
// QUICKWIT_INDEX_ID=logs
// QUICKWIT_API_KEY=optional-api-keySearch Operations
// Basic search
const results = await search.search({
query: 'error',
maxHits: 10,
});
// Search with sorting
const results = await search.search({
query: 'level:ERROR',
maxHits: 50,
sortField: 'timestamp',
sortOrder: 'desc',
});
// Search with field selection
const results = await search.search({
query: 'service:api',
maxHits: 20,
fetchFields: ['timestamp', 'level', 'message'],
});
// Search with pagination
const results = await search.search({
query: 'error',
maxHits: 10,
startOffset: 20,
});
// Search with snippet configuration
const results = await search.search({
query: 'database connection failed',
maxHits: 10,
snippetConfiguration: {
maxNumChars: 150,
numSnippets: 3,
fields: ['message', 'stacktrace'],
},
});Fuzzy Search
// Fuzzy search with auto fuzziness
const results = await search.fuzzySearch('conection faled', {
maxHits: 10,
});
// Fuzzy search with specific fuzziness
const results = await search.fuzzySearch('conection faled', {
maxHits: 10,
fuzziness: 2,
prefixLength: 2,
fields: ['message', 'stacktrace'],
});Document Operations
// Get document by ID
const doc = await search.getDocument('doc-id-123');
if (doc) {
console.log(doc);
} else {
console.log('Document not found');
}Index Management
// Get index info
const info = await search.getIndexInfo();
console.log(info.indexId, info.numDocs, info.size);
// List all indexes
const indexes = await search.listIndexes();
console.log(indexes); // ['logs', 'traces', 'metrics']
// Delete index
await search.deleteIndex('old-index');Health Check
const isHealthy = await search.healthCheck();
if (isHealthy) {
console.log('Quickwit is healthy');
}Aggregation
const results = await search.search({
query: 'error',
maxHits: 0, // Don't return hits
aggregationRequest: {
aggs: {
errors_by_level: {
terms: { field: 'level' },
},
errors_over_time: {
histogram: {
field: 'timestamp',
interval: '1h',
},
},
},
},
});
console.log(results.aggregations);API Reference
QuickwitSearchClient
Main client class for Quickwit search operations.
Constructor
constructor(config: QuickwitConfig)Config:
url- Quickwit server URL (required)indexId- Index ID to search (required)apiKey- Optional API key for authenticationtimeout- Request timeout in milliseconds (default:30000)
Methods
search(query: SearchQuery): Promise<SearchResponse>
Search documents in the index.
fuzzySearch(queryString: string, options?): Promise<SearchResponse>
Search with fuzzy matching.
getDocument(docId: string): Promise<Record<string, unknown> | null>
Get a document by ID.
getIndexInfo(): Promise<IndexInfo>
Get information about the index.
listIndexes(): Promise<string[]>
List all indexes.
deleteIndex(indexId?): Promise<void>
Delete an index.
healthCheck(): Promise<boolean>
Check if Quickwit is healthy.
Types
QuickwitConfig
interface QuickwitConfig {
url: string;
indexId: string;
apiKey?: string;
timeout?: number;
}SearchQuery
interface SearchQuery {
query: string;
maxHits?: number;
startOffset?: number;
sortField?: string;
sortOrder?: 'asc' | 'desc';
fetchFields?: string[];
aggregationRequest?: any;
snippetConfiguration?: {
maxNumChars?: number;
numSnippets?: number;
fields?: string[];
};
}SearchResponse
interface SearchResponse {
hits: Array<{
[key: string]: unknown;
}>;
aggregations?: any;
numHits: number;
elapsedTimeMicros: number;
}IndexInfo
interface IndexInfo {
indexId: string;
createdAt: string;
numDocs?: number;
size?: number;
}Query Syntax
Quickwit supports a powerful query syntax:
Field Search
// Search specific field
await search.search({ query: 'level:ERROR' });
// Multiple fields
await search.search({ query: 'level:ERROR AND service:api' });Wildcards
// Wildcard search
await search.search({ query: 'mess*' });Boolean Operators
// AND, OR, NOT
await search.search({ query: 'error AND NOT timeout' });
await search.search({ query: '(error OR fail) AND level:CRITICAL' });Range Queries
// Numeric ranges
await search.search({ query: 'status_code:[500 TO 599]' });
// Date ranges
await search.search({ query: 'timestamp:[2024-01-01 TO 2024-12-31]' });Fuzzy Search
Fuzzy search finds similar terms even with typos:
// Auto fuzziness (adapts based on term length)
const results = await search.fuzzySearch('conection faled');
// Specific edit distance
const results = await search.fuzzySearch('conection faled', {
fuzziness: 2, // Allow 2 edits
prefixLength: 2, // First 2 chars must match
});
// Field-specific fuzzy search
const results = await search.fuzzySearch('qery', {
fields: ['message', 'error_text'],
});Best Practices
- Use field-specific searches: Faster and more accurate
- Limit returned fields: Use
fetchFieldsfor better performance - Set appropriate maxHits: Don't fetch more than needed
- Use pagination: Use
startOffsetfor large result sets - Monitor index health: Check
getIndexInfo()periodically
Performance Tips
- Index frequently queried fields: Configure proper field mappings
- Use date filters: Always include time range in queries
- Limit aggregation scope: Use query filters with aggregations
- Fetch only needed fields: Use
fetchFieldsto reduce payload - Use snippets: Enable snippets for result preview
Error Handling
try {
const results = await search.search({ query: 'error' });
} catch (error) {
if (error.message.includes('index not found')) {
console.error('Index does not exist');
} else {
console.error('Search failed:', error);
}
}License
MIT
