
Alibabacloud Lindorm Agent Skill
- 50 installs
- 208 repo stars
- Updated August 4, 2026
- aliyun/alibabacloud-aiops-skills
alibabacloud-lindorm-agent-skill is a Claude skill covering development and operations for Alibaba Cloud Lindorm, a cloud-native multi-model database with wide-table, time-series, search, vector, and AI engines.
About
This skill provides guidance and operations for Alibaba Cloud Lindorm, a cloud-native multi-model database. It covers developer guidance (connection, SQL, table design, search, vector retrieval, AI engine calls, multimodal and knowledge-base search) and ops management (instance, monitoring, backup, migration, permissions, slow query). It routes a request through a decision tree to the correct reference document and requires answers to cite skill docs or official Alibaba Cloud documentation.
- Covers Alibaba Cloud Lindorm cloud-native multi-model database across dev guidance, ops management, and reference materi
- Includes wide-table/time-series/search/vector engines, AI engine calls, and multimodal image-text and knowledge-base sea
- Routes user requests through a decision tree to reference docs under references/01-dev, 02-ops, and 03-ref
Alibabacloud Lindorm Agent Skill by the numbers
- 50 all-time installs (skills.sh)
- +11 installs in the week ending Jun 23, 2026 (Skillselion tracking)
- Ranked #417 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
alibabacloud-lindorm-agent-skill capabilities & compatibility
- Works with
- aws
What alibabacloud-lindorm-agent-skill says it does
Alibaba Cloud Lindorm cloud native multi-model database Skill. Covers three domains: **Operations Management**, **Developer Guidance**, and **Reference Materials**.
Developer guidance includes classic SQL/search usage plus vector retrieval, Lindorm AI engine calls, multimodal image-text search, and private knowledge base search.
npx skills add https://github.com/aliyun/alibabacloud-aiops-skills --skill alibabacloud-lindorm-agent-skillAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 50 |
|---|---|
| repo stars | ★ 208 |
| Last updated | August 4, 2026 |
| Repository | aliyun/alibabacloud-aiops-skills ↗ |
What it does
Develop against and operate Alibaba Cloud Lindorm multi-model database, including SQL, search, vector, AI engine, and instance ops.
Who is it for?
Developers building on or operating Alibaba Cloud Lindorm (LindormTable, LindormTSDB, LindormSearch, vector, AI engine).
Skip if: Non-Lindorm databases or answering Lindorm questions from general training knowledge (docs must be referenced).
When should I use this skill?
The user asks about Lindorm, LindormTable/TSDB/Search, HBase compatibility, vector retrieval, multimodal search, or Lindorm instance ops.
By the numbers
- 3 documentation domains (01-dev, 02-ops, 03-ref)
Files
Lindorm Agent Skill
Alibaba Cloud Lindorm cloud native multi-model database Skill. Covers three domains: Operations Management, Developer Guidance, and Reference Materials. Developer guidance includes classic SQL/search usage plus vector retrieval, Lindorm AI engine calls, multimodal image-text search, and private knowledge base search.
Core Capability Matrix
| Category | Sub-Scenarios | Reference Docs |
|---|---|---|
| 01-Dev Guidance | Connection setup, quick start, SQL guide, table design, search engine usage, vector retrieval, AI engine calls, multimodal search, knowledge search | references/01-dev/ |
| 02-Ops Management | Instance mgmt, monitoring, error troubleshooting, storage analysis, connection diagnostics, backup & restore, migration, permissions, slow query | references/02-ops/ |
| 03-Reference | Lindorm CLI usage guide, HBase Shell guide, Aliyun CLI commands, RAM permissions, acceptance criteria | references/03-ref/ |
Decision Tree
User Request
├── Connection / DDL / SQL / Code examples → 01-dev
│ ├── Connection address / code → references/01-dev/connection-guide.md
│ ├── DDL / write / query examples → references/01-dev/quick-start-guide.md
│ ├── SQL connection & SQL-based application development → references/01-dev/sql-client-guide.md
│ ├── SQL syntax reference → references/01-dev/sql-operations.md
│ ├── MySQL compatibility → references/01-dev/sql-usage-notes.md
│ ├── Table design guide → references/01-dev/table-design.md
│ ├── Search engine standalone usage → references/01-dev/search-guide.md
│ ├── Vector engine usage through Search / Wide Table → references/01-dev/vector-guide.md
│ ├── Lindorm AI engine model calls → references/01-dev/ai-guide.md
│ ├── Multimodal image-text search scene → references/01-dev/multimodal-search-scene.md
│ └── Knowledge base search / private QA scene → references/01-dev/knowledge-search-scene.md
│
├── Instance / Monitoring / Errors / Performance / Storage / Connection / Scaling / Backup / Migration / Permissions / Slow query → 02-ops
│ ├── Instance management → references/02-ops/instance-management.md
│ ├── Monitoring / Alerts → references/02-ops/monitoring-guide.md
│ ├── Error codes → references/02-ops/error-troubleshoot.md
│ ├── Storage analysis → references/02-ops/storage-analysis.md
│ ├── Connection diagnostics → references/02-ops/connection-troubleshoot.md
│ ├── Scale up/down → references/02-ops/instance-management.md
│ ├── Backup & restore → references/02-ops/backup-restore.md
│ ├── Data migration → references/02-ops/data-migration.md
│ ├── Account & permissions → references/02-ops/user-permission.md
│ └── Slow query analysis → references/02-ops/slow-query-analysis.md
│
└── Command list / Permission reference / CLI tools / SQL execution → 03-ref
├── Lindorm CLI (install / execute SQL / preview data / test connection) → references/03-ref/lindorm-cli-guide.md
├── HBase Shell (alihbase) → references/03-ref/hbase-shell-guide.md
├── Aliyun CLI command list (`aliyun hitsdb ...`) → references/03-ref/related-commands.md
├── RAM permission list → references/03-ref/ram-policies.md
├── Aliyun CLI setup → references/03-ref/cli-installation-guide.md
├── Acceptance criteria → references/03-ref/acceptance-criteria.md
└── Verification methods → references/03-ref/verification-method.mdQuick Mapping Table
| User says | Scenario | Reference Doc |
|---|---|---|
| "how to connect / connection address" | Connection setup | references/01-dev/connection-guide.md |
| "create table / insert / query examples" | Quick start | references/01-dev/quick-start-guide.md |
| "how to create a table" | Table design | references/01-dev/table-design.md |
| "DBA / ops debugging via SQL" | SQL ops via CLI → SQL syntax | references/03-ref/lindorm-cli-guide.md → references/01-dev/sql-operations.md |
| "develop SQL app / code connection" | SQL client dev → SQL syntax | references/01-dev/sql-client-guide.md → references/01-dev/sql-operations.md |
| "SQL syntax" | SQL reference | references/01-dev/sql-operations.md |
| "how to use SQL" | SQL guide | references/01-dev/sql-client-guide.md |
| "MySQL compatibility" | SQL notes | references/01-dev/sql-usage-notes.md |
| "search engine usage / ES API / 30070" | Search engine standalone usage | references/01-dev/search-guide.md |
| "vector engine / KNN / RRF / IVFPQ / IVFBQ" | Vector retrieval through Search or Wide Table | references/01-dev/vector-guide.md |
| "AI engine / embedding / VL / rerank / 9002" | Lindorm AI engine model calls | references/01-dev/ai-guide.md |
| "multimodal retrieval / image-text search / image-to-image / text-to-image" | Multimodal image-text search scene | references/01-dev/multimodal-search-scene.md |
| "knowledge base retrieval / private QA / document chunking" | Knowledge base retrieval and QA scene | references/01-dev/knowledge-search-scene.md |
| "list instances / what instances exist" | Instance management | references/02-ops/instance-management.md |
| "CPU / memory / QPS / latency" | Monitoring query | references/02-ops/monitoring-guide.md |
| "configure alerts / alert notifications" | Monitoring alerts | references/02-ops/monitoring-guide.md |
| "got an error / error code" | Error troubleshooting | references/02-ops/error-troubleshoot.md |
| "slow query / query is slow" | Slow query analysis | references/02-ops/slow-query-analysis.md |
| "poor performance / high RT" | Monitoring query | references/02-ops/monitoring-guide.md |
| "cannot connect / connection timeout" | Connection diagnostics | references/02-ops/connection-troubleshoot.md |
| "storage usage" | Storage analysis | references/02-ops/storage-analysis.md |
| "hot/cold data / tiered storage" | Storage analysis | references/02-ops/storage-analysis.md |
| "scale up / add nodes" | Scaling | references/02-ops/instance-management.md |
| "backup / restore data" | Backup & restore | references/02-ops/backup-restore.md |
| "data migration / sync" | Data migration | references/02-ops/data-migration.md |
| "create account / permissions" | Permission management | references/02-ops/user-permission.md |
| "lindorm-cli / lindormcli" | Lindorm CLI | references/03-ref/lindorm-cli-guide.md |
| "execute SQL / run query" | SQL execution via CLI | references/03-ref/lindorm-cli-guide.md → references/01-dev/sql-operations.md |
| "SHOW TABLES / DESCRIBE / view table schema / list tables" | Schema exploration via CLI | references/03-ref/lindorm-cli-guide.md |
| "preview data / check data / query data" | Data preview via CLI | references/03-ref/lindorm-cli-guide.md |
| "test connection / verify connection" | Connection probe via CLI | references/03-ref/lindorm-cli-guide.md |
| "HBase Shell / hbase shell " | HBase Shell | references/03-ref/hbase-shell-guide.md |
Aliyun CLI
Prerequisites
When CLI invocation is required, the Agent must verify:
1. CLI installed: aliyun version >= 3.3.3; if not installed, see references/03-ref/cli-installation-guide.md 2. Plugins up-to-date:
aliyun configure set --auto-plugin-install true
aliyun plugin update3. Credentials configured:
Security Rules:
- NEVER read, echo, or print AK/SK values
- NEVER ask the user to input AK/SK directly in the conversation or command line
- ONLY use aliyun configure list to check credential status>
If no valid profile exists, STOP. Configure credentials outside of this session.
4. Permissions granted: Minimum AliyunLindormReadOnlyAccess + AliyunCloudMonitorReadOnlyAccess
[MUST] Permission Failure Handling: When any command or API call fails due to permission errors at any point during execution, follow this process:
1. Read references/03-ref/ram-policies.md to get the full list of permissions required by this SKILL2. If ram-permission-diagnose skill is available, use it to guide the user through requesting permissions. Otherwise, directly output the required RAM policy/action list, the error code, and step-by-step instructions for the user to request permissions from their administrator via RAM Console3. Pause and wait until the user confirms that the required permissions have been granted
Observability (MUST follow for every aliyun command)
Upon loading this skill, generate a random session ID (32-char lowercase hex string) once for the entire session. Use it as {session-id} below.>
Rule: Every `aliyun` CLI command that calls a cloud API MUST include the `--user-agent` flag.
Local utility commands (e.g.configure,plugin,version) do not support this flag and should be excluded.
>
```
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-lindorm-agent-skill/{session-id}
```
>
Example (assuming session-id is a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6):```bash
aliyun hitsdb get-lindorm-instance --instance-id ld-xxx \
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-lindorm-agent-skill/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
```
>
Do not skip, alter the format, or omit--user-agenton anyaliyunAPI command invocation.
Parameter Confirmation
Before executing any command, all user-configurable parameters (region, instance ID, time range, etc.) must be confirmed with the user.
Version Detection
For instance operations, the Agent must first call get-lindorm-instance to retrieve ServiceType and determine the instance version. All subsequent command selection depends on this:
| ServiceType | Version | Deployment |
|---|---|---|
lindorm | V1 | Single-AZ |
lindorm_multizone | V1 | Multi-AZ (HA) |
lindorm_multizone_basic | V1 | Multi-AZ (Basic) |
lindorm_v2 | V2 | Single-AZ |
lindorm_v2_multizone | V2 | Multi-AZ (Basic) |
lindorm_v2_multizone_ha | V2 | Multi-AZ (HA) |
General Policies
Region Policy
| Scenario | Command | Requires --region |
|---|---|---|
| Query all-region overview | get-instance-summary | ❌ Not needed |
| Query instance list | get-lindorm-instance-list | ✅ Required, default cn-shanghai |
| Query instance details / engine / storage / whitelist | Other hitsdb commands | ❌ Not needed, auto-resolved by --instance-id |
| Cloud monitoring query | cms commands | ❌ Not needed, region auto-resolved via instanceId |
Time Format
Cloud Monitor time parameter timezone notes:
- ✅
2026-04-14 08:00:00(local time, parsed as CST Beijing time) - ✅
1773897600000(Unix millisecond timestamp, no timezone ambiguity) - ✅
2026-04-14T08:00:00Z(ISO 8601 UTC full format, parsed as UTC, i.e. CST+8 = 16:00) - ❌
2026-04-14T08:00Z(ISO 8601 short format, no seconds — unsupported, returnsparse param time error) - ❌ Never use UTC Z format for user-intended local times (e.g. if user says "14:00", write
2026-04-14 14:00:00, not2026-04-14T14:00:00Z) - ⚠️ Note: local time and ISO 8601 Z format query different time windows — common source of timezone-related issues
Command Reference
Instance Management (hitsdb — Lindorm product alias)
| Command | Description | Example |
|---|---|---|
aliyun hitsdb describe-regions | List supported regions | aliyun hitsdb describe-regions |
aliyun hitsdb get-instance-summary | All-region instance overview (no --region needed) | aliyun hitsdb get-instance-summary |
aliyun hitsdb get-lindorm-instance-list | List instances (ID, status, engine flags; filterable by region/type) | aliyun hitsdb get-lindorm-instance-list --region cn-shanghai |
aliyun hitsdb get-lindorm-instance | Get config/version/status (ServiceType, engine node count, spec; no connection address) | aliyun hitsdb get-lindorm-instance --instance-id ld-xxx |
aliyun hitsdb get-lindorm-instance-engine-list | Get connection addresses (host:port per engine, public/private network) | aliyun hitsdb get-lindorm-instance-engine-list --instance-id ld-xxx |
aliyun hitsdb get-lindorm-fs-used-detail | V1 storage usage details | aliyun hitsdb get-lindorm-fs-used-detail --instance-id ld-xxx |
aliyun hitsdb get-lindorm-v2-storage-usage | V2 storage usage details | aliyun hitsdb get-lindorm-v2-storage-usage --instance-id ld-xxx |
aliyun hitsdb get-instance-ip-white-list | Get IP whitelist | aliyun hitsdb get-instance-ip-white-list --instance-id ld-xxx |
Engine Types
| Engine | V1 Code | V2 Code | Notes |
|---|---|---|---|
| LindormTable | lindorm | lindorm | HBase-compatible, supports SQL (recommended) |
| LindormTable (columnar) | — | lcolumn | V2 only |
| LindormTSDB | tsdb | tsdb | Time-series data storage |
| LindormSearch | solr | lsearch | Port 30070 (ES-compatible); solr is the legacy API code name. Solr API (port 10020) is deprecated/offline |
| Lindorm Tunnel Service | bds | bds | Formerly BDS, no external connection |
| Compute Engine | compute | compute | Flink streaming engine, no external connection |
| Stream Engine | stream | lstream | Port 33060 (MySQL protocol) |
| Message Engine | — | lmessage | Kafka-compatible, supports topic management and message production/consumption |
| Vector Engine | — | lvector | V2 only; built-in vector retrieval engine accessed through Search 30070 or Wide Table + Search |
| AI Engine | — | lai | V2 only; AI inference engine (embedding / VL / rerank / chat); port 9002 |
| LindormDFS | file | file | OSS-compatible storage (HDFS protocol, port 9000) |
Port Quick Reference
| Engine | Protocol | Port | Notes |
|---|---|---|---|
| LindormTable | MySQL protocol | 33060 | ✅ Recommended, preferred for SQL connections |
| LindormTable | HBase API | 30020 | HBase native API compatible |
| LindormTable | Avatica protocol | 30060 | ⚠️ Legacy only, migrate to MySQL protocol |
| LindormTable | Cassandra CQL | 9042 | ⚠️ Legacy only, Cassandra protocol compatible |
| Stream Engine | MySQL protocol | 33060 | Stream SQL via MySQL protocol |
| LindormTSDB | HTTP SQL | 8242 | HTTP SQL API |
| LindormSearch | ES-compatible | 30070 | Elasticsearch-compatible port, fixed. Solr API (port 10020) is deprecated/offline |
| Vector Engine | Built-in service | — | V2 only; no direct endpoint; use Search 30070 or Wide Table + Search |
| AI Engine | DashScope-compatible HTTP | 9002 | V2 only; uses x-ld-ak / x-ld-sk headers |
| LindormDFS | HDFS | 9000 | NameNode port |
Cloud Monitor API (aliyun cms)
| Command | Description | Example |
|---|---|---|
aliyun cms describe-metric-meta-list | List available monitoring metrics | aliyun cms describe-metric-meta-list --namespace acs_lindorm |
aliyun cms describe-metric-last | Get latest monitoring data (returns per-node data; Datapoints is a JSON string requiring secondary parsing) | aliyun cms describe-metric-last --namespace acs_lindorm --metric-name cpu_idle --dimensions '[{"instanceId":"ld-xxx"}]' |
aliyun cms describe-metric-data | Get historical trend data (aggregated by period, no host dimension) | aliyun cms describe-metric-data --namespace acs_lindorm --metric-name cpu_idle --dimensions '[{"instanceId":"ld-xxx"}]' --start-time "2026-04-14 08:00:00" --end-time "2026-04-14 09:00:00" --period 60 |
Metric Mapping
| User says | V1 Metric | V2 Metric | Unit |
|---|---|---|---|
| CPU usage | 100 - cpu_idle | 100 - cpu_idle | % |
| Memory usage | mem_used_percent | 1 - mem_free / mem_total | % |
| QPS | read_ops + write_ops | read_ops + write_ops | ops/s |
| Latency / RT | read_rt / get_rt_avg | read_rt / get_rt_avg | ms |
| P99 latency | get_rt_p99 / put_rt_p99 | — (no data) | ms |
| Hot storage usage rate | hot_storage_used_percent | get-lindorm-v2-storage-usage | % |
| Total storage usage rate | storage_used_percent | get-lindorm-v2-storage-usage | % |
| Hot storage bytes | hot_storage_used_bytes | get-lindorm-v2-storage-usage | bytes |
| Cold storage usage rate | cold_storage_used_percent | get-lindorm-v2-storage-usage | % |
| Cold storage bytes | cold_storage_used_bytes | get-lindorm-v2-storage-usage | bytes |
Full metric details: references/02-ops/monitoring-guide.md
Interaction Guidelines
Output Format
Monitoring Query:
[Summary] CPU usage 25% (normal)
[Time] <YYYY-MM-DD HH:MM–HH:MM>
[Trend] Stable (variance <10%)
[Details] avg 24.5%, max 32.1%, min 18.3%Error Troubleshooting:
[Error Code] InvalidParameter.InstanceId
[Meaning] Instance ID is invalid or does not exist
[Possible Causes] 1.xxx 2.xxx 3.xxx
[Resolution Steps] 1.xxx 2.xxx 3.xxxInstance List:
[Region] cn-shanghai [Count] 3
| ID | Name | Status | Engines |
|----|------|--------|---------|
| ld-xxx | prod | Running | LindormTable + LindormTSDB |Code Generation Standards
General Principles
1. Reference Skill documents first: Lindorm is domain-specific knowledge — information must come from references docs; direct answers from training knowledge are prohibited 2. Check official docs when Skill doesn't cover it: For scenarios not covered by references docs, consult official Alibaba Cloud documentation
Pre-Generation Checklist
- □ Connection parameter names are correct (MySQL protocol:
jdbc:mysql://host:33060, HBase API:hbase.zookeeper.quorum) - □ Port numbers are correct (LindormTable/Stream Engine MySQL 33060, HBase API 30020, LindormTSDB HTTP 8242, LindormSearch 30070)
- □ Include official documentation link
Lindorm AI Engine Guide
This guide describes how to use the Lindorm AI engine independently. The AI engine provides DashScope-compatible APIs for embeddings, visual understanding, reranking, and chat-based answer generation. Application code and agents should call models through the AI engine built into the Lindorm instance. Authentication uses the instance username and password through the x-ld-ak and x-ld-sk request headers. Do not use external platform API keys.
Connection and Connectivity
The AI engine always uses port 9002. Public endpoints usually contain -proxy-ai-pub; VPC endpoints usually contain -proxy-ai-vpc.
| Network type | Endpoint example | Applicable environment |
|---|---|---|
| VPC private network | <instance_id>-proxy-ai-vpc.lindorm.aliyuncs.com:9002 | Search pipelines, ECS, and services inside the VPC |
| Public network | <instance_id>-proxy-ai-pub.lindorm.aliyuncs.com:9002 | Local computers or public-network clients |
Before making public-network calls, confirm that the public endpoint of the AI engine is enabled and that the IP whitelist is configured. The public endpoint of the search engine and the public endpoint of the AI engine are different entries. Do not assume that the AI engine can be called just because the search engine public endpoint is enabled.
Connectivity check for port 9002
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-mode/v1/embeddings" \
-d '{
"model": "text-embedding-v4",
"input": "connectivity test"
}'A successful response should include embedding data. If the response returns 401 or 403, first check whether x-ld-ak and x-ld-sk come from the same Lindorm instance.
Model Configuration
| Model type | Typical model | Purpose | Key check |
|---|---|---|---|
| Text embedding | text-embedding-v4 | Vectorize text chunks in a knowledge base | The output dimension must equal the vector index dimension |
| Multimodal embedding | qwen2.5-vl-embedding / qwen3-vl-embedding | Build a unified image-text vector space for image-to-image and text-to-image search | Image and text queries must be written to the same vector field |
| VL | qwen3-vl-plus / qwen3-vl-flash | Recognize image URLs and generate image descriptions | The image URL must be accessible by the AI engine |
| Rerank | qwen3-rerank / gte-rerank-v2 | Rerank recalled candidates by query relevance | Preserve the original candidate array and map results back through results[*].index |
| Chat | qwen-plus / qwen3.5-plus | Generate knowledge-base answers | The prompt must restrict the model to answer only from the recalled context |
If the embedding model dimension and the vector index dimension are inconsistent, writes or queries will fail. Record embedding_model, vector_dimension, vector_field, and index_algorithm whenever a dataset is registered.
Embedding Calls
Text embeddings
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-mode/v1/embeddings" \
-d '{
"model": "text-embedding-v4",
"input": "Lindorm vector search supports hybrid full-text and vector retrieval"
}'Example response format:
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [0.0123, -0.0456]
}
],
"model": "text-embedding-v4",
"usage": {
"prompt_tokens": 12,
"total_tokens": 12
}
}Vector read path: data[0].embedding.
Multimodal embeddings
Multimodal embeddings are used for a unified image-text vector space. Use text for text input and image for image URL input.
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding" \
-d '{
"model": "multimodal-embedding-v1",
"input": {
"contents": [
{ "image": "https://example.com/product.jpg" }
]
}
}'Example response format:
{
"output": {
"embeddings": [
{
"embedding": [0.0123, -0.0456],
"index": 0,
"type": "dense"
}
]
},
"usage": {
"duration": 393,
"image_count": 1,
"image_tokens": 255,
"input_tokens": 0
},
"request_id": "<request_id>"
}Vector read path: output.embeddings[0].embedding. Before writing the vector, verify that its dimension is consistent with the target knn_vector.dimension.
VL Image Understanding Calls
VL models convert image URLs into structured or natural-language descriptions. They are commonly used during multimodal retrieval ingestion.
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-mode/v1/chat/completions" \
-d '{
"model": "qwen3-vl-plus",
"messages": [
{
"role": "user",
"content": [
{ "type": "image_url", "image_url": { "url": "https://example.com/product.jpg" } },
{ "type": "text", "text": "Describe the product, color, material, style, and applicable scenarios in this image. Output in English." }
]
}
]
}'Example response format:
{
"id": "<completion_id>",
"object": "chat.completion",
"created": 1770000000,
"model": "qwen3-vl-plus",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": "This is a product image. The main item is..."
}
}
],
"usage": {
"prompt_tokens": 256,
"completion_tokens": 80,
"total_tokens": 336
}
}Description read path: choices[0].message.content.
Rerank Calls
Reranking is a post-recall step and does not perform retrieval. The caller must keep the candidate document array and use the returned index to map each result back to the original candidate.
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-api/v1/reranks" \
-d '{
"model": "qwen3-rerank",
"query": "white shirt suitable for summer commuting",
"documents": [
"White short-sleeve cotton shirt suitable for commuting",
"Black thick coat suitable for winter"
],
"top_n": 2
}'Example response format:
{
"object": "list",
"results": [
{
"index": 0,
"relevance_score": 0.7791645121619432
},
{
"index": 1,
"relevance_score": 0.2119340804000243
}
],
"model": "qwen3-rerank",
"id": "<rerank_id>",
"usage": {
"total_tokens": 73
}
}Reranking rule: sort by results[*].relevance_score in descending order, then retrieve the original candidate document through results[*].index.
Chat-based Q&A Calls
Knowledge-base Q&A concatenates recalled text into context and then calls the Chat model. The prompt must restrict the model to answer only based on the provided context.
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-mode/v1/chat/completions" \
-d '{
"model": "qwen-plus",
"messages": [
{
"role": "system",
"content": "You are a private-domain knowledge-base Q&A assistant. Answer only according to the provided context."
},
{
"role": "user",
"content": "Known information: <retrieved_context>\nQuestion: <question>"
}
]
}'Answer read path: choices[0].message.content.
Error Handling
| Symptom | Possible cause | Handling |
|---|---|---|
| Connection timeout | Public endpoint is not enabled, whitelist is not configured, or a VPC endpoint is used from outside the VPC | Check the network type and whitelist |
401 / 403 | Missing request headers or incorrect password | Check x-ld-ak and x-ld-sk |
404 | Wrong port or path | Confirm that the port is 9002 and that the path starts with /dashscope/ |
| Embedding dimension mismatch | Model and index configuration are inconsistent | Reconfirm the model dimension and knn_vector.dimension |
| Empty VL content | Image URL is inaccessible or the image is too large | Verify that the image URL can be accessed by the server first |
| Empty rerank result | documents is empty or top_n is 0 | Check recalled candidates |
Evidence Output Format
[Connection] engine=AI endpoint=<masked_ai_endpoint>:9002 network=<public|vpc>
[Capability] type=<embedding|vl|rerank|chat> model=<model_name>
[Evidence] http_status=<status> request_id=<id> dim=<n> candidates=<n>
[Blocked] status=<BLOCKED_NETWORK|BLOCKED_AUTH|BLOCKED_MODEL|BLOCKED_INPUT> reason=<reason>Never include x-ld-sk, passwords, or complete secret values in reports.
Connection Information Retrieval Scenario
When the user asks "how do I connect to an instance", "what is the connection endpoint", or "which SDK do I need", follow this guide.
Trigger Conditions
Typical user expressions:
- "How do I connect to ld-xxx?"
- "Give me the connection endpoint."
- "How do I connect with Java?"
- "What is the port of the time series engine?"
- "Give me a connection example."
Core Principles
The agent is a solution provider, not a pointer to documentation: 1. Extract key information and organize it into a complete answer, including code examples, dependency configuration, and parameter descriptions. 2. Let the user obtain executable connection code inside the conversation without leaving the chat. 3. If the connection endpoint cannot be obtained from an API, clearly provide the exact console path, down to the button location. 4. Documentation links are supplementary references for users who want deeper details.
---
Execution Flow
Phase 1: Obtain basic instance information
Run the following commands to obtain the architecture version, connection endpoints, and network configuration of the instance:
# 1. Get instance details and identify the V1/V2 architecture
aliyun hitsdb get-lindorm-instance \
--instance-id <instance-id>
# 2. Get connection endpoints of each engine
aliyun hitsdb get-lindorm-instance-engine-list \
--instance-id <instance-id>Key information to extract:
| Item | Source field | Description |
|---|---|---|
| Architecture version | ServiceType | lindorm_v2* = V2 architecture; lindorm = V1 architecture |
| Connection endpoint | NetInfoList | Domain names and ports of each engine. This field is used by both V1 and V2 |
| Network type | NetType | "0" = public network available; "2" = VPC private network only. The value is a string and is the same for V1/V2 |
| Engine version | EngineList | Version number of each engine |
Note:get-lindorm-instance-engine-listreturnsNetInfoListandNetTypefor both V1 and V2. Another V2-only API,get-lindorm-v2-instance-details, returnsConnectAddressListandType=INTRANET/INTERNET. See Phase 2.
Endpoint domain format:
For endpoint formats, see sql-client-guide.md. It includes V1/V2 ServiceType identification logic and complete examples.
---
Phase 2: Confirm connection prerequisites
Before providing connection code, confirm the following two items.
1. Public-network access check
Method 1: Use `get-lindorm-instance-engine-list` for both V1 and V2
Check the string field NetType in NetInfoList:
"0": public network available"2": VPC private network only
Method 2: Use `get-lindorm-v2-instance-details` for V2 only
Check the Type field in ConnectAddressList:
INTERNET: public network availableINTRANET: VPC private network only
If only a VPC private endpoint exists (`NetType="2"` or `Type=INTRANET`):
⚠️ The SQL port of the current instance only supports VPC private-network access. To connect from a local computer:
1. Log on to the Lindorm console.
2. Click the instance ID, then go to Database Connection → Engine.
3. Click Enable Public Endpoint in the upper-right corner.
4. Configure the whitelist with your local IP address.
>
Alternatively, run the connection and operations on an Alibaba Cloud ECS instance in the same VPC as Lindorm.
2. Password retrieval and confirmation
V2 instances:
aliyun hitsdb get-lindorm-v2-instance-details \
--instance-id <instance-id>Extract the InitialRootPassword field. The username is root.
⚠️ Password retrieval and confirmation flow:
1. First connection: use InitialRootPassword.2. Connection failure or password error: stop execution and ask the user for the current password.
3. Change operations such as creating tables or modifying configurations: obtain explicit user authorization first.
V1 instances:
- Default username:
root - Default password:
root - If the password is forgotten: modify it through the cluster management system.
- Path: Lindorm console → instance ID → Database Connection → Wide Table Engine → Lindorm Insight → User Management
- After changing the password, restart the engine for the change to take effect.
---
Phase 3: Provide connection information
Organize the information obtained in Phases 1 and 2 and directly provide a complete connection plan to the user:
Instance ld-xxx has the following engines enabled:
- Wide table engine, version 2.8.6, V2 architecture
- Time series engine, version 2.7.15
[Connection endpoints] Obtained from API
- VPC private endpoint: ld-xxx-proxy-lindorm-vpc.lindorm.aliyuncs.com:33060
- Public endpoint: ld-xxx-proxy-lindorm-pub.lindorm.aliyuncs.com:33060
> ⚠️ When connecting from the public network, such as a local computer, use the public endpoint (`-pub`). Do not use the private endpoint (`-vpc`), otherwise the connection will time out.
[SQL credentials]
- Username: root
- Password: for a V2 instance, the `InitialRootPassword` has been obtained through `get-lindorm-v2-instance-details`; for a V1 instance, view it in Lindorm Insight → User Management in the console.Connectivity verification with the MySQL command line:
mysql -h <connection_endpoint> -P 33060 -u root -p \
--get-server-public-key --ssl-mode=DISABLEDAfter the connection succeeds, tell the user:
The connection has been verified successfully. Do you need a complete example for creating tables and writing data? Tell me the engine type, and I can provide complete code.
Engine port quick reference:
| Engine | Protocol | Port |
|---|---|---|
| Wide table engine | MySQL protocol, recommended | 33060 |
| Wide table engine | HBase API | 30020 |
| Time series engine | HTTP SQL API | 8242 |
| Search engine | Elasticsearch API | 30070 |
| Streaming engine | MySQL protocol | 33060 |
Connection method overview for each engine. Route the user to the correct guide according to the requirement:
| Engine | Connection method | Recommendation | Official documentation |
|---|---|---|---|
| Wide table engine | MySQL protocol SQL | ⭐ Recommended | Java JDBC, Python, and more languages in sql-client-guide.md |
| Wide table engine | HBase API | Common | Java, non-Java, and examples in quick-start-guide.md Scenario F |
| Wide table engine | Cassandra CQL | Existing workloads | Java Driver, non-Java |
| Wide table engine | S3 protocol | Existing workloads | Java, non-Java |
| Time series engine | JDBC Driver | ⭐ Recommended | JDBC Driver |
| Time series engine | HTTP SQL API | Lightweight | HTTP API |
| Search engine | Elasticsearch API | ⭐ Recommended | Java REST Client |
| Vector engine | Elasticsearch API | ⭐ Recommended | Reuse search engine port 30070. See the vector development guide |
| Streaming engine | MySQL protocol ETL SQL | ⭐ Recommended | Real-time ETL |
| Streaming engine | Kafka client | Data ingestion | Kafka write |
| LindormDFS | HDFS Shell / client | - | Underlying file access overview, operations guide |
| Compute engine | JDBC / JAR / Python | - | JDBC access, JAR job |
The Skill does not provide code examples for LindormDFS or the compute engine. If the user asks about them, guide the user to the official documentation above or the connection overview.
---
Phase 4: Whitelist check
The agent proactively checks the whitelist:
aliyun hitsdb get-instance-ip-white-list \
--instance-id <instance-id>Provide clear recommendations after analysis:
[Whitelist check]
Current whitelist configuration: 10.0.0.0/8
[Analysis]
- If your client IP is within 10.0.0.0/8, you can connect directly.
- If your client IP is not in the whitelist, you need to add it.
[Add a whitelist entry]
1. Log on to the [Lindorm console](https://lindorm.console.aliyun.com/) → on the instance list page, click the target instance ID → in the left navigation pane, click Access Control → Whitelist.
2. Click Create Whitelist Group, or modify an existing group.
3. Add the client IP. Use the VPC IP for private-network environments and the public IP for public-network environments.
- Single IP: 192.168.1.100
- CIDR block: 192.168.1.0/24
4. Click OK to save.
Tip: view your public IP with `curl ifconfig.me`.
[Security note]
- Avoid using 0.0.0.0/0, which allows all IP addresses and introduces security risks.
- Add only necessary IP addresses or VPC CIDR blocks.
Do you want me to help troubleshoot the connection issue?---
Next-Step Guidance
After connection verification succeeds, guide the user according to the requirement:
- Create tables, write data, or query data: see quick-start-guide.md, which contains complete examples for the wide table, time series, search, vector, and streaming engines.
- Troubleshoot connection failures: see connection-troubleshoot.md.
- Manage user permissions: see user-permission.md.
Knowledge Base Search Scene
This guide describes how to build private-domain knowledge-base Q&A with the Lindorm search engine, vector engine, and AI engine. The default path is: upload txt or CMRC-style JSON documents, split them into chunks, generate embeddings for chunk text, write the chunks to Lindorm, build a vector index, recall context through KNN or RRF, optionally rerank the candidates, and then call the Chat model to generate an answer.
Scenario Goals
| Phase | Capability |
|---|---|
| Data import | Support txt documents and CMRC-style JSON data |
| Data modeling | Store the original text in parent documents and store split text plus vectors in the chunk index |
| Vectorization | Generate vectors through the Lindorm AI embedding model |
| Data ingestion | Use search engine _bulk or wide table UPSERT |
| Index building | Explicitly build IVFPQ / IVFBQ indexes and check the status |
| Q&A retrieval | Recall by KNN/RRF, rerank candidates, and answer with Chat based on context |
Recommended Data Model
Direct Search Engine Mode
Parent document index <dataset_name>_parent:
| Field | Type | Description |
|---|---|---|
document_id | keyword | Document ID |
title | text | Title |
context | text | Original full text. It may be excluded from indexing |
metadata | object | Source, file name, and business tags |
Chunk index <dataset_name>_chunking:
| Field | Type | Description |
|---|---|---|
document_id | keyword | Parent document ID |
chunking_position | integer | Chunk position |
chunking_number | integer | Total chunk number or sequence number |
text_field | text | Chunk text |
vector_field | knn_vector | Chunk embedding |
metadata | object | Source information |
Wide Table Entry Mode
In wide table mode, create a table first and then create a search index with CREATE INDEX ... USING SEARCH. The pipeline automatically writes text into vector_field. For the specific DDL and pipeline template, see the sql-vector section in vector-guide.md.
Document Chunking
txt documents
Processing flow:
read txt
-> normalize whitespace
-> split by paragraph / sentence
-> merge to chunk_size
-> keep overlap
-> assign document_id + chunking_positionRecommended defaults:
| Parameter | Default value |
|---|---|
chunk_size | 500-800 Chinese characters |
chunk_overlap | 50-100 Chinese characters |
min_chunk_size | 50 Chinese characters |
document_id | File-name hash or user-specified ID |
CMRC-style JSON
CMRC data usually contains passages, questions, and answers. When building a knowledge base, prefer using the passage context as the parent document, and write the split context into the chunk index. Questions and answers can be used as metadata or a validation set, but should not directly replace the original text.
Index Creation
A knowledge base can use HNSW for quick validation, or IVFPQ / IVFBQ for large-scale low-cost retrieval. When an offline index is used, as in the reference project, explicitly build the index after data is written.
Example IVFBQ chunk index:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPUT "http://<search_endpoint>:30070/<dataset_name>_chunking?pretty" \
-d '{
"settings": {
"index": {
"number_of_shards": 4,
"knn": true,
"knn.offline.construction": true
}
},
"mappings": {
"_source": { "excludes": ["vector_field"] },
"properties": {
"document_id": { "type": "keyword" },
"chunking_position": { "type": "integer" },
"chunking_number": { "type": "integer" },
"text_field": { "type": "text", "analyzer": "ik_max_word" },
"vector_field": {
"type": "knn_vector",
"dimension": 1024,
"data_type": "float",
"method": {
"engine": "lvector",
"name": "ivfbq",
"space_type": "cosinesimil",
"parameters": {
"exbits": 2,
"nlist": 50
}
}
},
"metadata": { "type": "object" }
}
}
}'The parent document index may omit vector fields:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPUT "http://<search_endpoint>:30070/<dataset_name>_parent?pretty" \
-d '{
"settings": {
"index": { "number_of_shards": 2 }
},
"mappings": {
"properties": {
"document_id": { "type": "keyword" },
"title": { "type": "text", "analyzer": "ik_max_word" },
"context": { "type": "text", "index": false },
"metadata": { "type": "object" }
}
}
}'Vectorization and Data Ingestion
Call AI embedding for each chunk:
curl --connect-timeout 10 -m 60 \
-H 'Content-Type: application/json' \
-H 'x-ld-ak: <username>' \
-H 'x-ld-sk: <password>' \
-XPOST "http://<ai_endpoint>:9002/dashscope/compatible-mode/v1/embeddings" \
-d '{
"model": "text-embedding-v4",
"input": "<chunk_text>"
}'Write chunks:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/x-ndjson' \
-XPOST "http://<search_endpoint>:30070/_bulk" \
-d '
{"index":{"_index":"<dataset_name>_chunking","_id":"doc_001_0"}}
{"document_id":"doc_001","chunking_position":0,"chunking_number":1,"text_field":"<chunk_text>","vector_field":[0.01,0.02,0.03],"metadata":{"source":"upload"}}
'Verify after ingestion:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<dataset_name>_chunking/_count" \
-d '{
"query": { "match_all": {} }
}'Build IVFPQ / IVFBQ Indexes
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/_plugins/_vector/index/build" \
-d '{
"indexName": "<dataset_name>_chunking",
"fieldName": "vector_field",
"removeOldIndex": "true"
}'curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XGET "http://<search_endpoint>:30070/_plugins/_vector/index/tasks" \
-d '{
"indexName": "<dataset_name>_chunking",
"fieldName": "vector_field",
"taskIds": "[]"
}'Only mark the large-scale offline indexing process as successful after the task status is complete.
Knowledge Base Retrieval
KNN recall
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<dataset_name>_chunking/_search?pretty" \
-d '{
"size": 5,
"_source": ["document_id", "chunking_position", "text_field", "metadata"],
"query": {
"knn": {
"vector_field": {
"vector": [0.01, 0.02, 0.03],
"k": 10
}
}
},
"ext": {
"lvector": {
"nprobe": "80",
"reorder_factor": "2",
"client_refactor": "true"
}
}
}'RRF recall
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<dataset_name>_chunking/_search?pretty" \
-d '{
"size": 5,
"_source": ["document_id", "chunking_position", "text_field", "metadata"],
"query": {
"knn": {
"vector_field": {
"vector": [0.01, 0.02, 0.03],
"filter": {
"match": {
"text_field": "question text"
}
},
"k": 10
}
}
},
"ext": {
"lvector": {
"hybrid_search_type": "filter_rrf",
"rrf_rank_constant": "60",
"rrf_knn_weight_factor": "0.5"
}
}
}'Reranking and context assembly
Call the rerank API in ai-guide.md for the recalled text_field list. Then select the top chunks by score and concatenate the context:
Known information:
1. <chunk_1_text>
2. <chunk_2_text>
3. <chunk_3_text>
Answer the user question based only on the known information above. If the answer cannot be derived from the known information, answer "The question cannot be answered based on the known information." Do not fabricate.
Question: <question>Q&A generation
Use the Chat API in ai-guide.md. The answer must include retrieval evidence:
| Output item | Description |
|---|---|
answer | Answer based on recalled context |
citations | document_id, chunking_position, and score |
retrieval_mode | knn / rrf / rrf+rerank |
blocked_status | Network, authentication, schema, or index-building blocker |
Acceptance Evidence
[Target] instance=<instance_id> region=<region> network=<public|vpc>
[Dataset] name=<dataset_name> parent_index=<name> chunk_index=<name>
[Chunking] documents=<n> chunks=<n> chunk_size=<n> overlap=<n>
[Embedding] model=<model_name> dimension=<n> succeeded=<n> failed=<n>
[IndexBuild] algorithm=<hnsw|ivfpq|ivfbq> status=<FINISH|not_required|FAILED>
[Retrieval] mode=<knn|rrf|rrf+rerank> question=<masked_question> hits=<n>
[Answer] generated=<true|false> citations=<n>
[Blocked] status=<BLOCKED_NETWORK|BLOCKED_AUTH|BLOCKED_SCHEMA|BLOCKED_INDEX_BUILD|BLOCKED_MODEL> reason=<reason>Multimodal Image-Text Search Scene
This guide describes how to combine the Lindorm search engine, vector engine, and AI engine to build multimodal image-text retrieval. The reference workflow is: when CSV product data is imported, generate a VL description and a multimodal embedding for each image URL, write the CSV fields, image description, and vector into Lindorm, and then support image-to-image search, text-to-image search, and optional filters at query time.
Scenario Goals
| Capability | Default implementation |
|---|---|
| Instance registration | Record instance ID, region, account reference, access endpoint, and network type |
| Existing data retrieval | Perform schema discovery first, then run KNN / RRF according to the actual fields |
| New business onboarding | Infer the schema from CSV and use test_index_$date as the default index name |
| Image-to-image search | Image URL -> multimodal embedding -> KNN |
| Text-to-image search | Text -> multimodal embedding plus description full-text retrieval -> RRF |
| Filters | Put category, brand, price, time, tenant, and other fields into filter |
Instance Registration
Do not assume that multimodal retrieval has only one instance or one connection. Before execution, clearly identify the following fields:
| Field | Description |
|---|---|
instance_id | Lindorm instance ID |
region | Region where the instance resides |
network | public or vpc |
search_endpoint | Search engine endpoint, port 30070 |
wide_table_endpoint | Optional wide table SQL endpoint |
ai_endpoint | AI engine endpoint, port 9002 |
username / password | Credential reference. Do not display plaintext values in documents or logs |
dataset_name | Business dataset name |
index_name | Search index name. The default for a new index is test_index_$date |
vector_field | Recommended value is embedding. For existing data, derive it from schema discovery |
text_field | Recommended value is vl_description, or use the existing description field |
model_config | VL model, embedding model, rerank model, and vector dimension |
Existing Data Retrieval
1. Schema Discovery
If the user provides a dataset name but no schema, first call the search engine to inspect the index structure:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XGET "http://<search_endpoint>:30070/<index_name>?pretty"Identify the following roles:
| Role | Recommended fields | Identification rule |
|---|---|---|
| Image URL | url / image_url / pic_url | A keyword or text field whose value is an accessible image URL |
| Image description | vl_description / img_desc / description | A text field used for full-text retrieval or RRF |
| Multimodal vector | embedding / vector / custom field | type=knn_vector; record its dimension |
| Filter fields | category / brand / price / create_time | Scalar fields such as keyword, numeric, or date |
If multiple vector fields exist and the unified multimodal vector field cannot be determined, stop and ask the user to choose. Do not guess.
2. Image-to-image Search
Flow:
query_image_url
-> Lindorm AI multimodal embedding(input=image)
-> KNN on schema-derived vector_field
-> optional filter
-> return image_url + metadata + scoreRetrieval request:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_search?pretty" \
-d '{
"size": 10,
"_source": ["id", "url", "vl_description", "category", "brand"],
"query": {
"knn": {
"<vector_field>": {
"vector": [0.01, 0.02, 0.03],
"k": 10
}
}
},
"ext": {
"lvector": {
"ef_search": "200"
}
}
}'With filters:
"filter": {
"bool": {
"filter": [
{ "term": { "category": "dress" } },
{ "range": { "price": { "lte": 500 } } }
]
}
}3. Text-to-image Search
Use RRF hybrid retrieval by default: text embedding handles semantic recall, and the image description field handles full-text recall.
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_search?pretty" \
-d '{
"size": 10,
"_source": ["id", "url", "vl_description", "category", "brand"],
"query": {
"knn": {
"<vector_field>": {
"vector": [0.01, 0.02, 0.03],
"filter": {
"match": {
"<text_field>": "white shirt suitable for summer commuting"
}
},
"k": 10
}
}
},
"ext": {
"lvector": {
"hybrid_search_type": "filter_rrf",
"rrf_rank_constant": "60",
"rrf_knn_weight_factor": "0.5"
}
}
}'Optional rerank: call the rerank API in ai-guide.md for the <text_field> list in the recalled results, and sort again by relevance_score.
New Business Onboarding
1. CSV Input Convention
The CSV must contain at least one image URL column. Recommended fields:
| Field | Description |
|---|---|
id | Document ID. Generate a stable ID if this field is absent |
url / pic_url / image_url | Image URL |
title | Product title |
category | Category |
brand | Brand |
price | Price |
create_time | Creation time |
| Other fields | Write as metadata or normal filterable fields |
If no dataset name is specified, use test_index_$date. In implementation, $date should use the current date, for example test_index_20260512.
2. Index Creation
HNSW is suitable for quick onboarding by default. Recommended field names:
| Field | Type | Description |
|---|---|---|
id | keyword | Document ID |
url | keyword | Image URL |
title | text | Product title |
vl_description | text | Description generated by VL |
embedding | knn_vector | Multimodal vector |
category / brand | keyword | Filter fields |
price | double | Filter field |
create_time | date | Filter field |
For index creation, see the HNSW template in vector-guide.md. If the data volume exceeds one million records and IVFPQ / IVFBQ is selected, build the index after writing data and wait until the build is complete.
3. Data Ingestion
Processing flow for each CSV row:
read csv row
-> normalize id and image url
-> AI VL: image url -> vl_description
-> AI multimodal embedding: image url -> embedding
-> merge csv fields + vl_description + embedding
-> write to Lindorm Search _bulk
-> refresh/count validationRequirements:
| Check | Description |
|---|---|
| Image URL accessibility | Both VL and embedding depend on server-side access to the image |
| Embedding dimension | Must equal the index embedding.dimension |
| Failure handling | Record row number, ID, and error type for failed rows. Do not fabricate vectors |
| Bulk write | Use _bulk; control the batch size according to payload size |
| Completion validation | COUNT == valid CSV rows, or report the failed row list |
4. Retrieval Validation
After a new dataset is onboarded, validate at least the following items:
| Validation item | Success evidence |
|---|---|
| Index exists | GET /<index_name> returns the mapping |
| Data written | _count returns the number of valid rows |
| Image-to-image search | KNN returns hits, and the result contains image URLs |
| Text-to-image search | RRF returns hits, and the result contains the description field |
| Filters | Queries with category or brand filters still return results, or clearly explain why the result is empty |
Output Format
[Target] instance=<instance_id> region=<region> network=<public|vpc>
[Dataset] dataset=<dataset_name> index=<index_name> mode=<existing|new_csv>
[Schema] vector_field=<field> dimension=<n> text_field=<field> image_url_field=<field>
[Import] rows=<n> succeeded=<n> failed=<n>
[Search] image_knn_hits=<n> text_rrf_hits=<n> filter_hits=<n>
[Evidence] count=<n> sample_id=<id> sample_score=<score>
[Blocked] status=<BLOCKED_NETWORK|BLOCKED_AUTH|BLOCKED_SCHEMA|BLOCKED_MODEL> reason=<reason>Quick Start Scenarios
When the user asks beginner development questions such as "how do I create a table", "how do I write data", or "how do I query data", follow this guide.
Trigger Conditions
Typical user expressions:
- "How do I create a table?"
- "How do I write data?"
- "Give me a complete example."
- "How do I use the wide table engine?"
- "How should I store time series data?"
Core Principles
The agent should do the heavy lifting instead of asking the user to explore by themselves: 1. Extract complete code examples and provide executable code directly. 2. Attach documentation links only when they are needed as supplementary "learn more" references. 3. Goal: the user can run the code directly after receiving it, without searching documentation again.
---
Execution Flow
Step 1: Confirm the engine type
Ask which engine the user wants to use if it is not clear:
Which engine do you want to use?
1. Wide table engine, suitable for semi-structured data and compatible with HBase
2. Time series engine, suitable for IoT and monitoring time series data
3. Search engine, suitable for full-text search
Or tell me your use case, and I will recommend an engine.---
Step 2: Use reference documentation and generate a complete example
Mandatory requirement: before providing any code example, obtain information from the Skill references first. If the Skill references do not cover the case, query the official documentation for confirmation.
What the agent must do: based on the engine type, access the Alibaba Cloud Lindorm official documentation and obtain the latest examples.
Query target:
- Official documentation:
https://help.aliyun.com/zh/lindorm/ - Key information: complete code examples for table creation, data writes, and queries
Must extract and verify from official documentation:
- Latest Maven dependency versions, not old versions from training data
- Correct API usage, such as
Connectioninstead of deprecatedHConnection - Currently recommended table creation statement format
- Officially verified write and query code
- Best practices and performance optimization suggestions
Verification checklist:
Before providing code, the agent must confirm:
- Official documentation has been accessed for the latest example.
- The SDK version is up to date, such as alilindorm-table-sdk 2.x.
- The API usage is currently recommended and not deprecated.
- The table creation, write, and query code has been verified by official documentation.
- Official documentation links are attached for further learning.Then organize the result into complete executable code and provide it directly to the user.
---
Complete Examples by Engine Type
Scenario A: Wide Table Engine Quick Start
After checking the required references, provide a complete answer directly:
[Wide table engine complete example]
I have prepared complete code from connection to query, based on the latest official documentation.
[Step 1: Add Maven dependency]
<!-- MySQL protocol JDBC, recommended -->
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
</dependencies>
[Step 2: Connect to the instance]
import java.sql.*;
import java.util.Properties;
public class LindormQuickStart {
public static void main(String[] args) throws Exception {
// 1. Configure the connection. MySQL protocol is recommended.
// The agent selects the correct domain format according to instance ServiceType. See sql-client-guide.md.
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://<connection-endpoint>:33060/default?sslMode=disabled";
Properties props = new Properties();
props.setProperty("user", "your-username");
props.setProperty("password", "your-password");
Connection conn = DriverManager.getConnection(url, props);
Statement stmt = conn.createStatement();
// 2. Create a table.
stmt.execute("CREATE TABLE IF NOT EXISTS users (" +
"id VARCHAR PRIMARY KEY," +
"name VARCHAR," +
"age INT," +
"city VARCHAR)");
System.out.println("Table created successfully");
// 3. Write data.
stmt.execute("INSERT INTO users (id, name, age, city) VALUES " +
"('1', 'Alice', 25, 'Shanghai'), " +
"('2', 'Bob', 30, 'Beijing')");
System.out.println("Data written successfully");
// 4. Query data.
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE age > 20");
while (rs.next()) {
System.out.println("name=" + rs.getString("name") + ", age=" + rs.getInt("age"));
}
// 5. Close the connection.
rs.close();
stmt.close();
conn.close();
}
}
[Batch write optimization, recommended for production]
// Batch write with PreparedStatement.
String sql = "INSERT INTO users (id, name, age, city) VALUES (?, ?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
for (int i = 0; i < 10000; i++) {
pstmt.setString(1, "id_" + i);
pstmt.setString(2, "user_" + i);
pstmt.setInt(3, 20 + i % 50);
pstmt.setString(4, "city_" + i % 10);
pstmt.addBatch();
if (i % 1000 == 0) {
pstmt.executeBatch();
}
}
pstmt.executeBatch();
[Complete documentation]
For more information, such as secondary indexes, global indexes, and performance optimization:
https://help.aliyun.com/zh/lindorm/user-guide/lindorm-wide-table-engine---
Scenario B: Time Series Engine Quick Start
Extract the latest example from official documentation first.
Recommended connection method: official documentation recommends the JDBC Driver, which supports Java. The following example uses the HTTP SQL API because it is lightweight and suitable for quick validation in Python and other non-Java languages.
Reference documentation: https://help.aliyun.com/zh/lindorm/user-guide/http-sql-api-user-guide
Then provide complete code directly:
[Time series engine complete example, Python HTTP SQL API]
I have prepared complete code for writing and querying time series data.
[Step 1: Install dependency]
pip install requests
[Step 2: Complete example code]
import requests
import time
import datetime
# 1. Connection configuration.
host = "your-time-series-engine-endpoint"
port = 8242
url = f"http://{host}:{port}/api/v2/sql"
# 2. Create a table.
create_sql = """CREATE TABLE IF NOT EXISTS sensor (
device_id VARCHAR NOT NULL,
region VARCHAR NOT NULL,
time TIMESTAMP NOT NULL,
temperature DOUBLE,
humidity BIGINT,
PRIMARY KEY(device_id, region, time)
)"""
response = requests.post(url, data=create_sql)
print(f"Create table result: {response.status_code}")
# 3. Write one row.
insert_sql = f"""INSERT INTO sensor (device_id, region, time, temperature, humidity) VALUES
('F07A1260', 'north-cn', '{time.strftime('%Y-%m-%d %H:%M:%S')}', 75.3, 45)"""
response = requests.post(url, data=insert_sql)
print(f"Write result: {response.status_code}")
# 4. Batch write, recommended.
# Note: the primary key is (device_id, region, time). The same device with the same timestamp performs UPSERT overwrite.
now = datetime.datetime.now()
times = [(now + datetime.timedelta(seconds=i)).strftime('%Y-%m-%d %H:%M:%S') for i in range(4)]
batch_sql = f"""INSERT INTO sensor (device_id, region, time, temperature, humidity) VALUES
('F07A1260', 'north-cn', '{times[0]}', 75.3, 45),
('F07A1260', 'north-cn', '{times[1]}', 76.1, 47),
('F07A1261', 'south-cn', '{times[2]}', 18.1, 44),
('F07A1261', 'south-cn', '{times[3]}', 19.7, 44)"""
response = requests.post(url, data=batch_sql)
print(f"Batch write result: {response.status_code}")
# 5. Query data.
query_sql = "SELECT device_id, region, time, temperature FROM sensor LIMIT 100"
response = requests.post(url, data=query_sql)
result = response.json()
for row in result.get('rows', []):
print(f"device: {row[0]}, region: {row[1]}, time: {row[2]}, temperature: {row[3]}")
[Production recommendations]
1. Batch writes: write 100 to 1000 data points each time.
2. Data compression: the time series engine compresses data automatically; no manual configuration is required.
3. TTL: configure data expiration, such as 90 days.
4. Error handling: add retry logic and error logs.
[Complete documentation]
For more information, such as HTTP API parameters, downsampling, pre-aggregation, and TTL:
https://help.aliyun.com/zh/lindorm/user-guide/http-sql-api-user-guide---
Scenario C: Search Engine Quick Start
After checking the required references, provide a complete answer directly:
[Search engine complete example, compatible with Elasticsearch 7.10 API]
I have prepared complete search engine code with Java Low Level REST Client.
[Step 1: Obtain connection information]
Console -> Database Connection -> Search Engine tab
- Elasticsearch-compatible endpoint, either VPC or public network
- Default username and password
- Fixed port: 30070
[Step 2: Add Maven dependencies]
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
[Step 3: Connect and operate]
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.apache.http.util.EntityUtils;
public class LindormSearchQuickStart {
public static void main(String[] args) throws Exception {
// 1. Configure the connection. Elasticsearch-compatible API uses port 30070.
// Select the domain format according to ServiceType: V1=.lindorm.rds.aliyuncs.com, V2=.lindorm.aliyuncs.com.
String searchUrl = "ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com";
int searchPort = 30070;
String username = "user";
String password = "test";
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(username, password));
RestClientBuilder builder = RestClient.builder(new HttpHost(searchUrl, searchPort));
builder.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
try (RestClient client = builder.build()) {
String indexName = "products";
// 2. Create an index.
Request createReq = new Request("PUT", "/" + indexName);
createReq.setJsonEntity("{" +
" \"settings\":{\"index.number_of_shards\": 1}," +
" \"mappings\":{" +
" \"properties\":{" +
" \"name\":{\"type\":\"text\"}," +
" \"price\":{\"type\":\"double\"}," +
" \"category\":{\"type\":\"keyword\"}" +
" }" +
" }" +
"}");
Response resp = client.performRequest(createReq);
System.out.println("Create index: " + EntityUtils.toString(resp.getEntity()));
// 3. Bulk write documents.
Request bulkReq = new Request("POST", "/_bulk");
StringBuilder bulk = new StringBuilder();
bulk.append("{\"index\":{\"_index\":\"products\",\"_id\":\"1\"}}\n");
bulk.append("{\"name\":\"iPhone 15\",\"price\":7999.0,\"category\":\"phone\"}\n");
bulk.append("{\"index\":{\"_index\":\"products\",\"_id\":\"2\"}}\n");
bulk.append("{\"name\":\"MacBook Pro\",\"price\":14999.0,\"category\":\"computer\"}\n");
bulk.append("{\"index\":{\"_index\":\"products\",\"_id\":\"3\"}}\n");
bulk.append("{\"name\":\"AirPods Pro\",\"price\":1899.0,\"category\":\"earphones\"}\n");
bulkReq.setJsonEntity(bulk.toString());
client.performRequest(bulkReq);
System.out.println("Bulk write completed");
// 4. Refresh the index to make written data visible.
client.performRequest(new Request("POST", "/" + indexName + "/_refresh"));
// 5. Full-text search.
Request searchReq = new Request("GET", "/" + indexName + "/_search");
searchReq.setJsonEntity("{" +
" \"query\":{" +
" \"match\":{\"name\":\"Pro\"}" +
" }" +
"}");
resp = client.performRequest(searchReq);
System.out.println("Search result: " + EntityUtils.toString(resp.getEntity()));
// 6. Query a single document.
resp = client.performRequest(new Request("GET", "/" + indexName + "/_doc/1"));
System.out.println("Document 1: " + EntityUtils.toString(resp.getEntity()));
// 7. Delete the index.
client.performRequest(new Request("DELETE", "/" + indexName));
System.out.println("Index deleted");
}
}
}
[curl quick validation]
# Create index.
curl --connect-timeout 10 -m 60 -u user:password -X PUT "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/products" -H 'Content-Type: application/json' -d '
{"settings":{"index.number_of_shards":1},
"mappings":{"properties":{"name":{"type":"text"},"price":{"type":"double"}}}}'
# Write document.
curl --connect-timeout 10 -m 60 -u user:password -X POST "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/products/_doc/1" -H 'Content-Type: application/json' -d '{"name":"iPhone 15","price":7999}'
# Full-text search.
curl --connect-timeout 10 -m 60 -u user:password -X GET "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/products/_search" -H 'Content-Type: application/json' -d '{"query":{"match":{"name":"iPhone"}}}'
[Search engine key parameters]
| Parameter | Value | Description |
|-----------|-------|-------------|
| Port | 30070 | Fixed Elasticsearch-compatible port |
| Protocol | HTTP | HTTPS is not supported |
| Authentication | Basic Auth | Obtain username and password from the console |
| Compatibility | ES 7.10 | Compatible with Elasticsearch 7.10 and earlier APIs |
| Visibility after writes | Manual `_refresh` required | Or wait for automatic refresh, which defaults to 1 second |
[Complete documentation]
Search engine development guide:
https://help.aliyun.com/zh/lindorm/user-guide/lindormsearch/
https://help.aliyun.com/zh/lindorm/user-guide/java-low-level-rest-client---
Scenario D: Vector Engine Quick Start
After checking the required references, provide a complete answer directly:
[Vector engine complete example, accessed through the search engine ES API]
The Lindorm vector engine has no independent connection endpoint. Access it through the Elasticsearch-compatible API of the search engine on port 30070.
[Step 1: Obtain connection information]
Same as the search engine:
- Endpoint: Elasticsearch-compatible search engine endpoint, public or VPC
- Port: 30070
- Authentication: Basic Auth with username and password
[Step 2: Create a vector index with HNSW]
curl --connect-timeout 10 -m 60 -u user:password -X PUT "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/vector_test" -H 'Content-Type: application/json' -d '{
"settings": {
"number_of_shards": 1,
"knn": true
},
"mappings": {
"_source": {"excludes": ["vector1"]},
"properties": {
"vector1": {
"type": "knn_vector",
"dimension": 3,
"method": {
"engine": "lvector",
"name": "hnsw",
"space_type": "l2",
"parameters": {
"m": 24,
"ef_construction": 500
}
}
},
"field1": {"type": "long"},
"name": {"type": "keyword"}
}
}
}'
[Step 3: Write vector data]
curl --connect-timeout 10 -m 60 -u user:password -X POST "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/_bulk" -H 'Content-Type: application/x-ndjson' -d '
{"index":{"_index":"vector_test","_id":"1"}}
{"field1":1,"name":"apple","vector1":[1.2,1.3,1.4]}
{"index":{"_index":"vector_test","_id":"2"}}
{"field1":2,"name":"banana","vector1":[2.2,2.3,2.4]}
{"index":{"_index":"vector_test","_id":"3"}}
{"field1":3,"name":"orange","vector1":[3.2,3.3,3.4]}
'
# Refresh the index to make data visible.
curl --connect-timeout 10 -m 60 -u user:password -X POST "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/vector_test/_refresh"
[Step 4: KNN approximate search]
# Find the three vectors most similar to [1.3,1.4,1.5].
# Note: KNN search does not return _source by default. Explicitly specify returned fields.
curl --connect-timeout 10 -m 60 -u user:password -X GET "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/vector_test/_search" -H 'Content-Type: application/json' -d '{
"size": 3,
"_source": ["field1", "name"],
"query": {
"knn": {
"vector1": {
"vector": [1.3,1.4,1.5],
"k": 3
}
}
}
}'
[Step 5: Hybrid vector and scalar retrieval]
curl --connect-timeout 10 -m 60 -u user:password -X GET "http://ld-xxxx-proxy-search-pub.lindorm.rds.aliyuncs.com:30070/vector_test/_search" -H 'Content-Type: application/json' -d '{
"size": 3,
"_source": ["field1", "name"],
"query": {
"bool": {
"must": [
{
"knn": {
"vector1": {
"vector": [1.3,1.4,1.5],
"k": 10
}
}
}
],
"filter": [
{"range": {"field1": {"gte": 1, "lte": 3}}}
]
}
}
}'
[Vector engine key parameters]
| Parameter | Value | Description |
|-----------|-------|-------------|
| Access method | Search engine ES API | No independent endpoint. Reuse search engine port 30070 |
| Vector type | knn_vector | `dimension` must be specified |
| Index algorithm | hnsw | Supports `l2` and `cosinesimil`, both verified as usable |
| Visibility after writes | `_refresh` required | Or wait for automatic refresh |
[Complete documentation]
Vector engine development guide:
https://help.aliyun.com/zh/lindorm/user-guide/foundation---
Scenario E: Streaming Engine Quick Start
After checking the required references, provide a complete answer directly:
[Streaming engine complete example, ETL SQL real-time synchronization and precomputation]
The Lindorm streaming engine is accessed through the MySQL protocol on port 33060. It uses ETL SQL for real-time data synchronization and precomputation.
[Step 1: Create source and result tables in the wide table engine]
-- Connect to the wide table engine through the MySQL protocol.
mysql -h <wide-table-engine-endpoint> -P 33060 -u root -p
-- Create a source table.
CREATE TABLE source_tbl(id INT, val DOUBLE, PRIMARY KEY(id));
-- Create a mirror table as the real-time synchronization target.
CREATE TABLE sink_tbl(id INT, val DOUBLE, PRIMARY KEY(id));
[Step 2: Create ETL in the streaming engine for real-time mirroring]
-- Connect to the streaming engine through the MySQL protocol on the same port.
mysql -h <streaming-engine-endpoint> -P 33060 -u root -p
-- Create real-time synchronization ETL.
CREATE ETL sync_etl AS INSERT INTO sink_tbl SELECT * FROM source_tbl;
[Step 3: Verify real-time synchronization]
-- Insert data in the wide table engine.
INSERT INTO source_tbl(id, val) VALUES (1, 1.1), (2, 2.2);
-- Query the mirror table. Data has been synchronized in real time.
SELECT * FROM sink_tbl;
+------+------+
| id | val |
+------+------+
| 1 | 1.1 |
| 2 | 2.2 |
+------+------+
[Step 4: Multi-table JOIN precomputation]
-- Create user and order tables in the wide table engine.
CREATE TABLE user_tbl(user_id VARCHAR NOT NULL, user_name VARCHAR, PRIMARY KEY(user_id));
CREATE TABLE order_tbl(
order_id VARCHAR NOT NULL,
user_id VARCHAR,
amount DOUBLE,
PRIMARY KEY(order_id)
);
-- Create an index for the JOIN field. This is required.
CREATE INDEX idx_user_id ON order_tbl(user_id);
-- Create a denormalized result table that supports updates.
CREATE TABLE user_order_tbl(
order_id VARCHAR NOT NULL,
user_id VARCHAR,
user_name VARCHAR,
amount DOUBLE,
PRIMARY KEY(order_id)
) WITH (MUTABILITY='MUTABLE_UDT');
-- Create JOIN ETL in the streaming engine. Use full table names.
CREATE ETL join_etl AS
INSERT INTO `lindorm_table`.`default`.`user_order_tbl`(order_id, user_id, user_name, amount)
SELECT o.order_id, o.user_id, u.user_name, o.amount
FROM `lindorm_table`.`default`.`order_tbl` o
JOIN `lindorm_table`.`default`.`user_tbl` u ON o.user_id = u.user_id;
-- Insert test data.
INSERT INTO user_tbl VALUES ('U001', 'Alice'), ('U002', 'Bob');
INSERT INTO order_tbl VALUES ('O001', 'U001', 100.0), ('O002', 'U001', 200.0);
-- Query the result table. JOIN results have been generated in real time.
SELECT * FROM user_order_tbl;
+----------+---------+-----------+--------+
| order_id | user_id | user_name | amount |
+----------+---------+-----------+--------+
| O001 | U001 | Alice | 100.0 |
| O002 | U001 | Alice | 200.0 |
+----------+---------+-----------+--------+
[Streaming engine key parameters]
| Parameter | Value | Description |
|-----------|-------|-------------|
| Connection method | MySQL protocol | Same as the wide table engine, port 33060 |
| Core syntax | CREATE ETL | `CREATE ETL name AS INSERT INTO ... SELECT ...` |
| Table name format | Full path | Use `lindorm_table.default.tablename` for cross-database queries |
| JOIN requirement | Index required | JOIN keys must have secondary indexes, otherwise an error is returned |
| Result table | MUTABLE_UDT | Precomputed result tables must support updates |
| Real-time behavior | Near real time | Data changes are synchronized within seconds |
[Manage ETL]
-- Show all ETLs.
SHOW ETLS;
-- Drop an ETL.
DROP ETL IF EXISTS etl_name;
[Complete documentation]
Streaming engine development guide:
https://help.aliyun.com/zh/lindorm/user-guide/real-time-etl---
Scenario F: Wide Table Engine HBase API Quick Start
Applicable scenarios: migration of existing HBase applications and KV-level operations. For new users, prefer Scenario A, which uses MySQL protocol SQL.
Reference documentation: https://help.aliyun.com/zh/lindorm/user-guide/use-the-hbase-api-for-java-to-connect-to-and-use-the-wide-table-engine
HBase SDK installation: https://help.aliyun.com/zh/lindorm/user-guide/install-and-upgrade-hbase-sdk-for-java
Extract the latest example from official documentation first:
[Wide table engine HBase API complete example, Java]
[Step 1: Add Maven dependency]
<!-- Select the corresponding Alibaba Cloud distribution according to the open-source HBase client version. -->
<!-- HBase 1.x users -->
<dependency>
<groupId>com.aliyun.hbase</groupId>
<artifactId>alihbase-client</artifactId>
<version>1.8.8</version>
</dependency>
<!-- HBase 2.x users -->
<dependency>
<groupId>com.aliyun.hbase</groupId>
<artifactId>alihbase-client</artifactId>
<version>2.8.7</version>
</dependency>
[Step 2: Configure the connection]
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
public class LindormHBaseQuickStart {
public static void main(String[] args) throws Exception {
// 1. Configure the connection on port 30020.
// Obtain the HBase API endpoint from the Database Connection page in the console.
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "<connection-endpoint>:30020");
conf.set("hbase.client.username", "username");
conf.set("hbase.client.password", "password");
// 2. Create a connection. It is thread-safe, should be reused globally, and closed when the program exits.
Connection connection = ConnectionFactory.createConnection(conf);
[Step 3: DDL operations, such as create and delete tables]
try (Admin admin = connection.getAdmin()) {
// Create a table.
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("tablename"));
htd.addFamily(new HColumnDescriptor(Bytes.toBytes("family")));
// Create a table with one region. Use pre-splitting in production to avoid hotspots.
admin.createTable(htd);
// Pre-split table creation example, recommended.
// byte[][] splitKeys = new byte[][] {
// Bytes.toBytes("10"), Bytes.toBytes("20"), Bytes.toBytes("30")
// };
// admin.createTable(htd, splitKeys);
// Disable the table before truncate or delete.
// admin.disableTable(TableName.valueOf("tablename"));
// admin.truncateTable(TableName.valueOf("tablename"), true);
// admin.deleteTable(TableName.valueOf("tablename"));
}
[Step 4: DML operations, such as read, write, delete, and scan]
// Table is not thread-safe. Each thread must obtain its own Table object from Connection.
try (Table table = connection.getTable(TableName.valueOf("tablename"))) {
// Insert data.
Put put = new Put(Bytes.toBytes("row"));
put.addColumn(Bytes.toBytes("family"), Bytes.toBytes("qualifier"), Bytes.toBytes("value"));
table.put(put);
// Read a single row.
Get get = new Get(Bytes.toBytes("row"));
Result res = table.get(get);
// Delete one row.
Delete delete = new Delete(Bytes.toBytes("row"));
table.delete(delete);
// Range scan.
Scan scan = new Scan(Bytes.toBytes("startRow"), Bytes.toBytes("endRow"));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
// Process query results.
}
scanner.close();
}
connection.close();
}
}
[HBase API key parameters]
| Parameter | Value | Description |
|-----------|-------|-------------|
| Port | 30020 | Fixed port dedicated to the HBase API |
| Connection | Thread-safe | Create once globally and close when the program exits |
| Table | Not thread-safe | Each thread must obtain its own Table object |
| Table creation | Pre-splitting recommended | A single region causes hotspots. Pre-splitting is required in production |
| Authentication | Username and password | Obtain them from the console |
[Complete documentation]
- Java: https://help.aliyun.com/zh/lindorm/user-guide/use-the-hbase-api-for-java-to-connect-to-and-use-the-wide-table-engine
- Non-Java, Thrift2: https://help.aliyun.com/zh/lindorm/user-guide/use-the-hbase-api-for-a-non-java-language-to-connect-to-and-use-the-wide-table-engineLindorm Search Engine Guide
This guide describes how to use the Lindorm search engine independently. The search engine exposes an Elasticsearch-compatible access endpoint on the fixed port 30070. It is used for full-text search, filtered search, index inspection, count statistics, and also serves as the main entry point for vector retrieval.
Applicable Scenarios
| User intent | Handling method |
|---|---|
| Check whether the search engine is reachable | Confirm that LindormSearch is enabled for the instance, then probe port 30070 |
| View an existing index schema | Call GET /<index_name> and read mappings.properties |
| Count documents in an index | Call POST /<index_name>/_count |
| Full-text search | Use match / multi_match to query text fields |
| Filtered search | Use term / range / bool.filter to query structured fields |
| Vector retrieval | Route to vector-guide.md; calls still go through the search engine on port 30070 |
Connection and Connectivity
The search engine endpoint comes from the instance engine list or the Database Connection page in the console. Public endpoints usually contain -proxy-search-pub; private endpoints usually contain -proxy-search-vpc.
| Network type | Endpoint example | Applicable environment |
|---|---|---|
| VPC private network | <instance_id>-proxy-search-vpc.lindorm.aliyuncs.com:30070 | ECS, containers, and services inside the VPC |
| Public network | <instance_id>-proxy-search-pub.lindorm.aliyuncs.com:30070 | Local computers or public-network clients |
Before public-network access, complete the whitelist check: obtain the client public IP, query the instance whitelist, and append the IP to the default group if it is not already included. Do not overwrite existing whitelist entries. For CLI commands and console paths, see references/01-dev/connection-guide.md and references/02-ops/connection-troubleshoot.md.
Port 30070 probe
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-XGET "http://<search_endpoint>:30070/"A successful response usually returns cluster or service metadata. If the request times out, distinguish the following cases first:
| Symptom | Possible cause | Handling |
|---|---|---|
| DNS resolution failure | Incorrect endpoint or public endpoint not enabled | Retrieve the search engine endpoint again |
| connect timeout | Public whitelist does not allow the client, or a VPC endpoint is used from outside the VPC | Check the whitelist and network type |
401 / 403 | Incorrect username or password | Use the Lindorm account and password of the current instance |
404 | Incorrect access path | Access / or /<index_name> first |
Basic ES Usage
The following examples all use the search engine entry point http://<search_endpoint>:30070 and HTTP Basic Auth. Do not write real passwords to documents, logs, or eval output.
View index schema
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XGET "http://<search_endpoint>:30070/<index_name>?pretty"Key information to extract:
| Field | Purpose |
|---|---|
settings.index.number_of_shards | Determine shard and resource configuration |
mappings.properties | Determine field types, full-text fields, keyword fields, and vector fields |
knn_vector.dimension | Verify model dimension before vector retrieval |
method.name / method.engine | Identify index algorithms such as HNSW, IVFPQ, and IVFBQ |
Count documents
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_count" \
-d '{
"query": { "match_all": {} }
}'Count with filters:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_count" \
-d '{
"query": {
"bool": {
"filter": [
{ "term": { "category": "phone" } },
{ "range": { "price": { "gte": 1000 } } }
]
}
}
}'Full-text search
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_search?pretty" \
-d '{
"size": 10,
"_source": ["id", "title", "content", "category"],
"query": {
"match": {
"content": "vector retrieval"
}
}
}'Search multiple fields:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_search?pretty" \
-d '{
"size": 10,
"_source": true,
"query": {
"multi_match": {
"query": "wireless earphones noise cancellation",
"fields": ["title^2", "description"]
}
}
}'Filtered search
Put structured filters in bool.filter. Filter conditions do not affect relevance scoring and are suitable for fields such as category, tenant, time, and price.
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_search?pretty" \
-d '{
"size": 10,
"_source": ["id", "title", "category", "price", "create_time"],
"query": {
"bool": {
"must": [
{ "match": { "description": "lightweight laptop" } }
],
"filter": [
{ "term": { "category": "computer" } },
{ "range": { "price": { "lte": 8000 } } },
{ "range": { "create_time": { "gte": "2026-01-01 00:00:00" } } }
]
}
}
}'Write and Refresh
Write a single document:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-H 'Content-Type: application/json' \
-XPOST "http://<search_endpoint>:30070/<index_name>/_doc/<doc_id>" \
-d '{
"title": "Lindorm Search",
"content": "The search engine supports full-text search and filtered search",
"category": "guide"
}'Refresh the index to make writes immediately visible:
curl --connect-timeout 10 -m 60 \
-u <username>:<password> \
-XPOST "http://<search_endpoint>:30070/<index_name>/_refresh"Evidence Output Format
When the agent reports search engine operation results, provide auditable evidence:
[Target] instance=<instance_id> region=<region> network=<public|vpc>
[Connection] engine=search endpoint=<masked_search_endpoint>:30070
[Index] name=<index_name> schema_status=<ok|blocked|failed>
[Action] type=<connectivity|get_index|count|fulltext|filter>
[Evidence] http_status=<status> count=<n> hits=<n>
[Blocked] status=<BLOCKED_NETWORK|BLOCKED_AUTH|BLOCKED_SCHEMA> reason=<reason>Do not output passwords, access keys, or complete sensitive connection strings in the final answer.
Lindorm SQL Client Development Guide
This document provides development references for connecting to Lindorm SQL in multiple languages, including Java, Python, Go, C/C++, C#, Rust, PHP, Node.js, connection pool configuration, and framework integration.
Recommendation: The MySQL protocol is more stable, reliable, and performant. New users are advised to connect to the wide table engine through the MySQL protocol.
Common Prerequisites
- The MySQL protocol compatibility feature is enabled. Console path: Database Connection > Wide Table Engine.
- The client IP has been added to the whitelist.
- For the MySQL protocol port, follow
SKILL.md-> "Code generation specifications / port quick reference".
Connection Domain Format
Lindorm instances have two architecture versions, V1 and V2, and their domain formats are different. During execution, the agent should:
1. Query instance details to obtain ServiceType. 2. Identify the architecture type:
lindorm_v2*-> use the V2 domain format.lindorm-> use the V1 domain format.
3. Automatically fill in the correct connection endpoint.
| Architecture | ServiceType | Domain format | Private endpoint example | Public endpoint example |
|---|---|---|---|---|
| V2 | lindorm_v2* | *.lindorm.aliyuncs.com | ld-xxx-proxy-lindorm-vpc.lindorm.aliyuncs.com:33060 | ld-xxx-proxy-lindorm-pub.lindorm.aliyuncs.com:33060 |
| V1 | lindorm | *.lindorm.rds.aliyuncs.com | ld-xxx-proxy-lindorm.lindorm.rds.aliyuncs.com:33060 | ld-xxx-proxy-lindorm-public.lindorm.rds.aliyuncs.com:33060 |
A V1 wide table engine has two MySQL endpoints:proxy-lindormandproxy-sql-lindorm. They provide the same functionality. Either one can be used.
>
A V1 public endpoint is available only after public access is enabled. By default, only the private endpoint is provided. The public endpoint suffix is -public.>
How to obtain it: console -> instance details -> Database Connection, or run aliyun hitsdb get-lindorm-instance-engine-list --instance-id <id>.---
Notes
- Answer user questions only based on content explicitly documented in this Skill. Do not infer, associate, or generate SQL syntax, parameters, features, or configurations that are not present in the documentation from training knowledge.
- If the documentation does not contain relevant information, clearly tell the user "This content is not included in the current documentation" and guide the user to Alibaba Cloud official documentation at
help.aliyun.comfor confirmation. - Generated code examples must be based on templates in the documentation. Parameters and syntax must be consistent with the documentation.
---
Execution Steps
Step 1: Identify the user's development language
---
Step 2: Select the connection method based on the development language
Official documentation links
SQL-based application development: https://help.aliyun.com/zh/lindorm/user-guide/add-connect-wide-table-engines-through-lindorm-query-language/
Application development with the MySQL protocol, recommended
1. Java
- JDBC interface: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-java-jdbc-interface
- Druid connection pool: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-java-connection-pool-druid
- LindormDataSource: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-lindormdatasource
- ORM framework MyBatis: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-java-orm-framework-mybatis
2. Python
- Native Python: https://help.aliyun.com/zh/lindorm/user-guide/python-based-application-development-1
- ORM framework: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-python-orm-framework
3. Go
- Native Go: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-go
- ORM framework: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-go-orm-framework
4. C
- C API: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-c-api
5. C#
- Native C#: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-c
6. Rust
- Native Rust: https://help.aliyun.com/zh/lindorm/user-guide/rust-based-application-development
7. PHP
- Native PHP: https://help.aliyun.com/zh/lindorm/user-guide/php-based-application-development
8. Node.js
- Native Node.js: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-node-js
9. ODBC
- ODBC interface: https://help.aliyun.com/zh/lindorm/user-guide/application-development-based-on-odbc
Avatica protocol, existing-workload maintenance only
1. Java
- JDBC interface: https://help.aliyun.com/zh/lindorm/user-guide/call-java-api-operations-in-sql-based-connection-to-and-usage-of-lindormtable
- Druid connection pool: https://help.aliyun.com/zh/lindorm/user-guide/through-the-connection-pool-druid-connection-wide-table-engine
2. Python
- DB-API: https://help.aliyun.com/zh/lindorm/user-guide/use-the-lindorm-sql-api-for-a-non-java-language-to-connect-to-and-use-the-wide-table-engine-lindormtable
- DBUtils connection pool: https://help.aliyun.com/zh/lindorm/user-guide/use-dbutils-to-connect-to-lindormtable
3. Go
- database/sql interface: https://help.aliyun.com/zh/lindorm/user-guide/use-the-apis-provided-by-the-database-or-sql-library-of-go-to-develop-applications
---
Step 3: Provide connection examples
---
Common Connection Examples
MySQL Protocol, Recommended
All examples use the <connection-endpoint> placeholder. The agent automatically fills in the correct V1/V2 domain according to the instance ServiceType.
Java
1. JDBC Interface
Dependency:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>Connection code:
Class.forName("com.mysql.cj.jdbc.Driver");
String username = "root";
String password = "your_password";
String database = "default";
String url = "jdbc:mysql://<connection-endpoint>:33060/" + database
+ "?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true"
+ "&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true"
+ "&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000";
Properties properties = new Properties();
properties.put("user", username);
properties.put("password", password);
Connection connection = DriverManager.getConnection(url, properties);CRUD example:
// Create table
try (Statement stmt = connection.createStatement()) {
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS user_test(id VARCHAR, name VARCHAR, PRIMARY KEY(id))");
}
// Batch insert. INSERT is recommended and has the same semantics as UPSERT.
String sql = "INSERT INTO user_test(id, name) VALUES(?, ?)";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
for (int i = 0; i < 100; i++) {
ps.setString(1, "id" + i);
ps.setString(2, "name" + i);
ps.addBatch();
}
ps.executeBatch(); // Recommended batchSize: 50-100
}
// Query
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM user_test WHERE id = ?")) {
ps.setString(1, "id1");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println("id=" + rs.getString(1) + ", name=" + rs.getString(2));
}
}
// Close the connection
connection.close();2. Druid Connection Pool
Dependency:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>Configuration file (druid.properties):
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://<connection-endpoint>:33060/default?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000&socketTimeout=120000
username=root
password=your_password
init=true
initialSize=10
maxActive=40
minIdle=40
maxWait=30000
# Avoid uneven connection load distribution
druid.phyMaxUseCount=10000
phyTimeoutMillis=1800000
# Connection keepalive
druid.keepAlive=true
druid.keepAliveBetweenTimeMillis=120000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
maxEvictableIdleTimeMillis=600000
testWhileIdle=true
testOnBorrow=false
testOnReturn=falseInitialize the connection pool:
Properties properties = new Properties();
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// Use the connection
try (Connection conn = dataSource.getConnection()) {
// Execute SQL...
}3. LindormDataSource, Officially Recommended
It encapsulates out-of-the-box best-practice configurations and supports zone-aware access in multi-zone deployments.
Dependency:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-sql-datasource</artifactId>
<version>2.2.1.4</version>
</dependency>Usage:
LindormDataSourceConfig config = new LindormDataSourceConfig();
config.setJdbcUrl("jdbc:mysql://<connection-endpoint>:33060/default");
config.setUsername("root");
config.setPassword("your_password");
config.setMaximumPoolSize(30);
LindormDataSource dataSource = new LindormDataSource(config);
try (Connection conn = dataSource.getConnection()) {
// Execute SQL...
}Spring Boot 2.x integration:
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-sql-datasource-springboot-starter</artifactId>
<version>2.2.1.4</version>
</dependency># application.yml
spring:
datasource:
lindorm:
jdbc-url: jdbc:mysql://<connection-endpoint>:33060/default
username: root
password: your_password
maximum-pool-size: 304. MyBatis Framework
Dependency:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.14</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>Configuration file (mybatis-config.xml):
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://<connection-endpoint>:33060/default?sslMode=disabled&allowPublicKeyRetrieval=true"/>
<property name="username" value="root"/>
<property name="password" value="your_password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="org.example.UserMapper"/>
</mappers>
</configuration>Mapper example:
public interface UserMapper {
@Update("CREATE TABLE IF NOT EXISTS demo_user(id INT, name VARCHAR, PRIMARY KEY(id))")
void createUserTable();
@Insert("UPSERT INTO demo_user(id, name) VALUES(#{userId}, #{userName})")
int upsertUser(User user);
@Select("SELECT * FROM demo_user WHERE id = #{userId}")
User selectOneUser(@Param("userId") int userId);
@Delete("DELETE FROM demo_user WHERE id = #{userId}")
int deleteUser(@Param("userId") int userId);
}---
Python
1. mysql-connector-python
Installation: pip install mysql-connector-python==8.0.15
Direct connection mode:
import mysql.connector
connection = mysql.connector.connect(
host='<connection-endpoint>',
port=33060,
user='root',
passwd='your_password',
database='default'
)
cursor = connection.cursor(prepared=True)
# Create table
cursor.execute("CREATE TABLE IF NOT EXISTS test_python(c1 INTEGER, c2 INTEGER, c3 VARCHAR, PRIMARY KEY(c1))")
# Insert data. Use parameterization to prevent SQL injection.
cursor.execute("UPSERT INTO test_python(c1, c2, c3) VALUES(?, ?, ?)", (1, 1, 'value1'))
# Query
cursor.execute("SELECT * FROM test_python WHERE c1 = ?", (1,))
print(cursor.fetchall())
cursor.close()
connection.close()Connection pool mode:
from mysql.connector import pooling
connection_pool = pooling.MySQLConnectionPool(
pool_name="mypool",
pool_size=20,
host='<connection-endpoint>',
port=33060,
user='root',
password='your_password',
database='default'
)
connection = connection_pool.get_connection()
cursor = connection.cursor(prepared=True)
# ... Execute SQL
cursor.close()
connection.close() # Return to the connection pool2. SQLAlchemy ORM
Installation:
pip install PyMySQL
pip install SQLAlchemyExample:
from sqlalchemy import create_engine, Column, String, Integer, Float
from sqlalchemy.orm import declarative_base, sessionmaker
Base = declarative_base()
class Player(Base):
__tablename__ = 'player'
player_id = Column(Integer, primary_key=True, autoincrement=False)
player_name = Column(String(255))
player_height = Column(Float)
engine = create_engine('mysql+pymysql://root:your_password@<connection-endpoint>:33060/default')
Session = sessionmaker(bind=engine)
# Create table
Base.metadata.create_all(engine)
# Write data
session = Session()
session.add(Player(player_id=1001, player_name="john", player_height=2.08))
session.commit()
# Query
rows = session.query(Player).filter(Player.player_id == 1001).all()
print([str(row) for row in rows])---
Go
1. database/sql + MySQL Driver
Dependency (go.mod):
require github.com/go-sql-driver/mysql v1.7.1Example:
package main
import (
"database/sql"
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
)
func main() {
url := "root:your_password@tcp(<connection-endpoint>:33060)/default?timeout=10s"
db, err := sql.Open("mysql", url)
if err != nil {
panic(err)
}
defer db.Close()
// Connection pool configuration
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(20)
db.SetConnMaxIdleTime(8 * time.Minute)
db.SetConnMaxLifetime(30 * time.Minute)
// Create table
db.Exec("CREATE TABLE IF NOT EXISTS user_test(id INT, name VARCHAR, age INT, PRIMARY KEY(id))")
// Insert with parameter binding
stmt, _ := db.Prepare("UPSERT INTO user_test(id, name, age) VALUES(?, ?, ?)")
stmt.Exec(1, "zhangsan", 17)
// Query
rows, _ := db.Query("SELECT * FROM user_test")
defer rows.Close()
for rows.Next() {
var id, age int
var name string
rows.Scan(&id, &name, &age)
fmt.Printf("id=%d, name=%s, age=%d\n", id, name, age)
}
}2. GORM Framework
Dependency:
require (
gorm.io/driver/mysql v1.5.1
gorm.io/gorm v1.25.4
)Example:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Product struct {
ID int64 `gorm:"primaryKey;autoIncrement:false"`
Code string `gorm:"type:varchar"`
Price float64
}
func main() {
dsn := "root:your_password@tcp(<connection-endpoint>:33060)/default"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// Important: Lindorm does not support transactions. Disable them.
session := db.Session(&gorm.Session{SkipDefaultTransaction: true})
// Create table
session.Migrator().CreateTable(&Product{})
// Write
session.Create(&Product{ID: 1, Code: "D42", Price: 100.1})
// Query
var product Product
session.First(&product, 1)
}---
C/C++
Installation (CentOS): yum install mysql-devel
Example:
#include <stdio.h>
#include "mysql/mysql.h"
int main() {
MYSQL conn;
mysql_init(&conn);
if (!mysql_real_connect(&conn,
"<connection-endpoint>",
"root", "your_password", "default", 33060, NULL, 0)) {
printf("Connection failed: %s\n", mysql_error(&conn));
return 1;
}
// Create table
mysql_query(&conn, "CREATE TABLE IF NOT EXISTS user_test(id INT, name VARCHAR, PRIMARY KEY(id))");
// Insert data
mysql_query(&conn, "UPSERT INTO user_test(id, name) VALUES(1, 'test')");
// Query data
mysql_query(&conn, "SELECT * FROM user_test");
MYSQL_RES *result = mysql_store_result(&conn);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
printf("id=%s, name=%s\n", row[0], row[1]);
}
mysql_close(&conn);
return 0;
}Compile: gcc -o demo demo.c $(mysql_config --cflags) $(mysql_config --libs)
---
C#
Installation: dotnet add package MySql.Data -v 8.0.11
Example:
using MySql.Data.MySqlClient;
string connStr = "server=<connection-endpoint>;UID=root;database=default;port=33060;password=your_password";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
MySqlCommand cmd = new MySqlCommand("SHOW DATABASES", conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) {
Console.WriteLine(rdr[0]);
}
conn.Close();---
Rust
Dependency (Cargo.toml):
[dependencies]
mysql = "*"Example:
use mysql::*;
use mysql::prelude::*;
fn main() {
let opts = OptsBuilder::new()
.ip_or_hostname(Some("<connection-endpoint>"))
.user(Some("root"))
.pass(Some("your_password"))
.db_name(Some("default"))
.tcp_port(33060);
let pool = Pool::new(opts).unwrap();
let mut conn = pool.get_conn().unwrap();
// Create table
conn.query_drop("CREATE TABLE IF NOT EXISTS user_test(id INT, name VARCHAR, PRIMARY KEY(id))").unwrap();
// Insert
conn.exec_drop("UPSERT INTO user_test(id, name) VALUES(?, ?)", (1, "test")).unwrap();
// Query
let result: Vec<(i32, String)> = conn.query("SELECT * FROM user_test").unwrap();
for (id, name) in result {
println!("id={}, name={}", id, name);
}
}---
PHP
Requirement: PHP 8.0+ with the php-mysql module installed
Example:
<?php
$lindorm_addr = "<connection-endpoint>";
$lindorm_username = "root";
$lindorm_password = "your_password";
$lindorm_database = "default";
$lindorm_port = 33060;
$conn = mysqli_connect($lindorm_addr, $lindorm_username, $lindorm_password, $lindorm_database, $lindorm_port);
// Create table
mysqli_query($conn, "CREATE TABLE IF NOT EXISTS user_test(id INT, name VARCHAR, PRIMARY KEY(id))");
// Insert data
mysqli_query($conn, "UPSERT INTO user_test(id, name) VALUES(1, 'test')");
// Query data
$result = mysqli_query($conn, "SELECT * FROM user_test");
while ($row = mysqli_fetch_array($result)) {
printf("id=%d, name=%s\n", $row["id"], $row["name"]);
}
mysqli_close($conn);
?>---
Node.js
Installation: npm install mysql2
Example:
var mysql = require('mysql2');
var connection = mysql.createConnection({
host: '<connection-endpoint>',
port: 33060,
user: 'root',
password: 'your_password',
database: 'default',
connectTimeout: 10000
});
connection.connect(function(err) {
if (err) throw err;
console.log("Connected!");
// Query
connection.query('SHOW DATABASES', function(err, results) {
if (err) throw err;
console.log(results);
});
connection.end();
});---
ODBC
Installation (Linux):
# Download the MySQL ODBC driver: https://dev.mysql.com/downloads/connector/odbc/
yum install unixODBC-develConfiguration (/etc/odbcinst.ini):
[MySQL]
Description = ODBC for MySQL
Driver64 = /usr/lib64/libmyodbc8a.so
Setup64 = /usr/lib64/libmyodbc8w.so
FileUsage = 1C code example:
#include <sql.h>
#include <sqlext.h>
int main() {
SQLHENV env;
SQLHDBC dbc;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
ret = SQLDriverConnect(dbc, NULL,
(SQLCHAR*)"DRIVER={MySQL};SERVER=<connection-endpoint>;PORT=33060;DATABASE=default;USER=root;PASSWORD=your_password",
SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
if (ret == SQL_SUCCESS) {
printf("Connection succeeded\n");
// ... Execute SQL
}
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
return 0;
}---
Avatica Protocol, Existing-Workload Maintenance Only
Note: The Avatica protocol is currently in existing-workload maintenance mode and is not recommended for new users.
>
The Avatica domain format is slightly different:
- V2: ld-xxx-proxy-lindorm-vpc.lindorm.aliyuncs.com:30060- V1: ld-xxx-proxy-lindorm.lindorm.rds.aliyuncs.com:30060Java (Avatica)
Dependency:
<dependency>
<groupId>com.aliyun.lindorm</groupId>
<artifactId>lindorm-all-client</artifactId>
<version>2.2.1.3</version>
</dependency>Connection code:
String url = "jdbc:lindorm:table:url=http://<connection-endpoint>:30060";
Properties properties = new Properties();
properties.put("user", "root");
properties.put("password", "your_password");
properties.put("database", "default");
Connection connection = DriverManager.getConnection(url, properties);Python (Avatica - phoenixdb)
Installation: pip install phoenixdb==1.2.0
import phoenixdb
connect_kw_args = {
'lindorm_user': 'root',
'lindorm_password': 'your_password',
'database': 'default'
}
database_url = 'http://<connection-endpoint>:30060'
connection = phoenixdb.connect(database_url, autocommit=True, **connect_kw_args)
with connection.cursor() as cursor:
cursor.execute("SELECT * FROM test_table")
print(cursor.fetchall())
connection.close()Go (Avatica)
Dependency (go.mod):
require github.com/apache/calcite-avatica-go/v5 v5.0.0
replace github.com/apache/calcite-avatica-go/v5 => github.com/aliyun/alibabacloud-lindorm-go-sql-driver/v5 v5.0.6---
Best Practices
Recommended Connection Parameters
| Parameter | Recommended value | Description |
|---|---|---|
| sslMode | disabled | Do not use SSL to improve performance |
| useServerPrepStmts | true | Enable server-side prepared statements |
| rewriteBatchedStatements | true | Optimize batch write performance |
| cachePrepStmts | true | Cache prepared statements |
| prepStmtCacheSize | 100 | Number of cached statements |
Write Performance Optimization
1. Use batch writes: recommended batchSize is 50-100. 2. Use INSERT instead of UPSERT: under the MySQL protocol, INSERT has the same semantics as UPSERT but benefits from client-side optimization. 3. Increase concurrency: improve write throughput with multiple threads or goroutines.
Connection Pool Configuration
1. Do not keep connections alive for too long. Configure phyMaxUseCount and phyTimeoutMillis. 2. Call close() promptly after queries are complete to return connections to the pool. 3. Enable connection keepalive checks.
Notes
- Lindorm does not support transactions: disable transactions when using ORM frameworks such as GORM.
- UPDATE supports only single-row updates: the WHERE condition must specify the full primary key.
- Idle connection timeout: the server proactively closes connections that have been idle for 10 minutes.
Backup and Restore Scenarios
Trigger Conditions
- "How do I back up Lindorm data?"
- "How can I restore data to yesterday's state?"
- "Can you help me view the backup list?"
- "How can I recover data after accidental deletion?"
- "What is the automatic backup cycle?"
---
Agent Behavior Principles
Safety boundary: Query backup information + guide manual operations. Restore operations require user confirmation.
1. The Agent currently has no API for directly querying the backup list. 2. Provide the console path for configuring automatic backup policies. 3. Provide restore steps, but do not directly execute restore operations. 4. Restore operations overwrite current data and require explicit user confirmation.
---
Official Documentation
| Scenario | Documentation Link |
|---|---|
| Enable backup and restore | https://help.aliyun.com/zh/lindorm/user-guide/backup-and-restoration |
| Automatic backup configuration | https://help.aliyun.com/zh/lindorm/user-guide/automatic-backup-of-data-of-lindorm-wide-tables |
| Restore to the current instance | https://help.aliyun.com/zh/lindorm/user-guide/restore-backup-data-to-the-instance-that-corresponds-to-the-original-data |
| Value-added service fees | https://help.aliyun.com/zh/lindorm/product-overview/value-added-services-pricing |
---
Backup Capabilities by Engine
| Engine | Backup and Restore Capability | Description |
|---|---|---|
| Wide table engine | ✅ Supported | Complete backup and restore capabilities described in this document |
| Search engine | ❌ No independent backup | The source data of search indexes is in wide tables. After wide table backup restoration, search indexes must be rebuilt. |
| Time series engine | ❌ No independent backup | No official backup and restore documentation is available yet. |
| Compute engine | ❌ No backup required | Stateless Spark compute service. Job results are written back to storage engines, and storage engine backup already covers them. |
Official backup and restore capabilities are provided only for the wide table engine. Other engines currently have no independent backup solution.
| Type | Description | Configuration Method |
|---|---|---|
| Full backup | Backs up complete table data and schemas | Configure the cycle and scope in the console |
| Incremental backup | Automatically backs up changed data | Runs automatically after enablement, with no configuration required |
Configurable Parameters for Full Backup
| Parameter | Description | Optional Range | Recommended Value |
|---|---|---|---|
| Backup tables | Specifies the backup scope | * for the entire database, or namespace:table format. For example, default:test indicates tables whose names start with test in the default namespace. | *, entire database |
| Full backup cycle | Trigger interval | 3 to 10 days | 7 days |
| Next full backup time | Start time | Off-peak hours are recommended | 02:00 |
| Number of retained full backups | Number of retained backups | 3 to 12 | 7 |
Backup and Restore Performance Reference (Not Configurable)
| Metric | Description | Reference Value |
|---|---|---|
| RPO | Maximum acceptable data loss during a failure | < 30 seconds, real-time incremental synchronization |
| Full restore speed | Maximum OSS bandwidth / single LTS node | 1 GB/s / 100 MB/s |
| Incremental restore speed | Single Lindorm destination cluster node / single LTS node | 30 to 40 MB/s / 100 MB/s |
---
Scenario A: Configure Automatic Backup
Step 1: Enable Backup and Restore
1. Log on to the Lindorm console. 2. On the instance list page, click the target instance ID. 3. In the left-side navigation pane, click Wide Table Engine → Backup and Restore. 4. Click "Enable Now".
- If search indexes or data subscription are not enabled: You are redirected to the specification change page. Select the LTS Core specification and number of nodes. For specification selection, see the value-added service documentation. Then click "Buy Now".
- If search indexes or data subscription are already enabled: Enable directly without specification change.
⚠️ Unsupported instance types: Lindorm new-version instances and single-node instances do not currently support backup and restore.
Step 2: Configure a Full Backup Policy
1. In the left-side navigation pane, click Wide Table Engine → Backup and Restore → Full Backup. 2. Click "Create". 3. Configure parameters. For recommended values, see the parameter table above:
- Backup tables:
*, entire database, or a specified table such asdefault:user_table. - Full backup cycle: 7 days. A cycle that is too short may prevent backup completion, and a cycle that is too long affects restore time.
- Next full backup time: 02:00, during off-peak hours.
- Number of retained full backups: 7.
4. Click "Confirm".
⚠️ Space evaluation: Insufficient backup space causes backup interruption. Full backup space ≈ (number of retained backups + 1) × size of a single full backup. Incremental space ≈ log retention days × daily incremental LOG size. You can view the size of a single full backup in Wide Table Engine → Backup and Restore → Full Backup. The incremental LOG size can be estimated from the write speed obtained through monitoring.
Verify Backup
After configuration, the system automatically executes backup at the configured time. View path: Wide Table Engine → Backup and Restore → Full Backup List.
Notes
- The first backup scans the entire table and takes a long time.
- The backup process does not affect business reads and writes.
- Incremental backup runs automatically and requires no configuration.
- Backup storage is billed on a pay-as-you-go basis. For detailed prices, see Value-added service billing.
---
Scenario B: Restore Historical Data
Prerequisites
1. Backup and restore has been enabled for the instance. ⚠️ Lindorm new-version instances and single-node instances are not currently supported. 2. A backup before the accidental deletion exists. View path: Wide Table Engine → Backup and Restore → Full Backup List. 3. The backup time point is within the retention period.
Method 1: Restore to the Current Instance
⚠️ Risk warning: This operation overwrites the specified table data in the current instance, and the table is unavailable during restoration. It is recommended to clear the original table data before restoration or verify the operation in a test instance.
1. Log on to the Lindorm console. 2. On the instance list page, click the target instance ID. 3. In the left-side navigation pane, click Wide Table Engine → Backup and Restore. 4. In the full backup list, click "Start Data Restoration". 5. Configure parameters:
- Restore cluster: Current instance. ⚠️ After a version upgrade, backup data of the original version cannot be used to restore the new version.
- Time point: Select the backup time point.
- Full database restore: No. Specifying tables is recommended.
- Restore tables: Write one table per line in
namespace:tableformat, such asdefault:testTable. To restore to another table name, usenamespace:table/namespace:table2, such asdefault:testTable/default:testTable2.
6. Click "OK".
Method 2: Restore to Another Instance
Applicable scenarios: data migration and environment replication.
Notes:
- The destination instance must have sufficient storage space.
- The destination instance version must be the same as the source instance version.
- Cross-version restoration is not supported.
Query Restore Progress
Console path: Wide Table Engine → Backup and Restore → Restore List.
Post-restore Verification
-- Verify the data volume.
SELECT COUNT(*) FROM user_table;
-- View sample data.
SELECT * FROM user_table LIMIT 10;---
FAQ
| Question | Cause | Solution |
|---|---|---|
| Restore failed: insufficient storage space | The destination instance does not have enough space | Scale out storage space and retry, or clean up useless data |
| Restore failed: version incompatible | The source and destination instance versions are inconsistent | Make sure the versions are consistent. After a version upgrade, backup data of the original version cannot be used to restore the new version. |
| What is the latest restorable time point? | WAL backup cycle to OSS | Normally, at most 30 seconds of data is lost |
| How long does restoration take? | Depends on the data volume | Full restore is about 100 MB/s on a single LTS node, and incremental restore is about 30 to 40 MB/s |
| Can data be restored to another table name? | Supported | Use the format namespace:table/namespace:table2 to restore a table to another table with the same data |
---
Missing Parameter Follow-up Questions
| Missing Parameter | Follow-up Question | Default Strategy |
|---|---|---|
| Instance ID | "Which Lindorm instance needs backup configuration?" | Guide the user to operate in the console |
| Backup cycle | "How often do you want to back up data? The recommended value is 7 days." | Default to 7 days |
| Retention count | "How many backups do you need to retain? The recommended value is 7." | Default to 7 |
| Restore time point | "Which time point do you want to restore data to?" | List recent backups for selection |
| Restore scope | "Do you need to restore all tables or specified tables?" | By default, remind the user that specifying tables is safer |
---
Related Scenarios
- Data migration after backup →
data-migration.md - Performance verification after restoration →
monitoring-guide.md
Related skills
FAQ
What engines does Lindorm cover here?
Wide-table, time-series, search, and vector engines plus AI engine calls and multimodal image-text and knowledge-base search.
How are answers grounded?
Answers must reference skill documents or official Alibaba Cloud documentation; direct responses from training knowledge are prohibited.