How to query a Database inside VPN
What This Pattern Does
Allows services to send raw ElasticSearch/OpenSearch queries directly to the database through a standardized command handler, bypassing traditional API layers for complex queries.
How to Implement
1. Add Raw Query Method to Your Service
Add this method to your Elasticsearch service class:
async sendRawQuery(query: ElasticSearchQueryBody): Promise<unknown> {
const result = await this.search(query);
return result;
}
2. Create Command Handler
Create a handler file (cmd.yourServiceRawQuery.execute.ts):
import { type Handler, type Message } from "@receeve-gmbh/sqs-handler";
import { MessageHandlerError } from "@receeve-gmbh/errors";
import type { ElasticSearchQueryBody } from "../entities/elasticsearch";
interface RawQueryMessage extends Message {
payload: ElasticSearchQueryBody;
}
export default class CommandYourServiceRawQueryHandler
implements Handler<unknown, RawQueryMessage>
{
public constructor(private readonly yourService: YourServiceClass) {}
public async processMessage(incomingMessage: RawQueryMessage): Promise<unknown> {
const { attributes, payload } = incomingMessage;
try {
return await this.yourService.sendRawQuery(payload);
} catch (innerError) {
throw new MessageHandlerError({ innerError, attributes });
}
}
}
3. Register Handler
Add the handler to your message routing configuration.
How to Use
Basic Query Example
{
"query": {
"bool": {
"must": [
{ "term": { "clientId": "your-client-id" } },
{ "range": { "totalAmount": { "gte": 1000 } } }
]
}
},
"size": 100
}
Aggregation Example
{
"query": {
"bool": {
"must": [{ "term": { "clientId": "your-client-id" } }]
}
},
"size": 0,
"aggs": {
"amounts_by_currency": {
"terms": { "field": "currency" }
}
}
}
When to Use
- ✅ Complex analytical queries
- ✅ Custom aggregations
- ✅ Debugging data issues
- ✅ Advanced filtering beyond standard APIs
When NOT to Use
- ❌ Simple CRUD operations
- ❌ User-facing features
- ❌ Data modifications (read-only pattern)
Important Rules
- Always include
clientIdfiltering for data isolation - **Use
size: 0**for aggregation-only queries - Add proper error handling in your handler
- Log queries for debugging and monitoring
That's it! This pattern gives you direct access to ElasticSearch capabilities while maintaining service architecture standards.