---
name: polardbx-zero-pxsearch
description: Claim a dedicated PolarDB-X Search cluster (OpenSearch 3.0 compatible) with a public REST endpoint, a private account and a Dashboards URL. Full-text search with Chinese analyzers, vector kNN, BM25 hybrid ranking and RAG. Use when the user asks for a search engine, an OpenSearch/Elasticsearch-like index, vector or hybrid retrieval, or a RAG backend.
compatibility: Any HTTP client (curl, Python, LangChain). The cluster endpoint speaks plain **HTTP on port 9200** — not HTTPS; an `https://` URL will fail to connect. The claim call whitelists your egress IP automatically; if your data-plane egress differs, add it via the whitelist endpoint below.
metadata:
  version: 0.1.0
  homepage: https://zero.polardbx.com/
---

# PolarDB-X Zero — PXSearch

PXSearch is a **standalone search engine backed by PolarDB-X Search**, compatible with the OpenSearch 3.0 REST API.
One claim gives you a **dedicated cluster**: a public REST endpoint, a dedicated username/password, an IP whitelist,
and a Dashboards web console. Talk to it with plain HTTP — no SDK required.

**The cluster lives for 24 hours.** When it expires — or when you release it — the cluster and **every index and
document on it are destroyed**, with no warning and no recovery. Tell the user this before they put data in, and
treat PXSearch as scratch space: anything that must survive belongs in a durable store.

**Treat the password like a passphrase.** Keep it out of shell history and logs — the examples below load it into an
environment variable rather than passing `-u user:pass` on the command line.

## Claim it

```sh
CLAIM=$(curl -fsSL -X POST 'https://zero.polardbx.com/api/v1/pxsearch/instances' \
  -H 'Content-Type: application/json' -d '{}')
echo "$CLAIM"
```

The response carries an `instance.assignmentId`. Credentials (username + password) are provisioned asynchronously
(whitelist + account creation take a few seconds), so poll the credentials endpoint until `password` is present:

```sh
ASSIGN=$(echo "$CLAIM" | python3 -c 'import json,sys;print(json.load(sys.stdin)["instance"]["assignmentId"])')
SESSION=$(echo "$CLAIM" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("token",""))')

for i in $(seq 1 40); do
  CRED=$(curl -fsSL "https://zero.polardbx.com/api/v1/pxsearch/instances/$ASSIGN/credentials" \
    -H "x-pxz-token: $SESSION")
  PW=$(echo "$CRED" | python3 -c 'import json,sys;print(json.load(sys.stdin)["instance"].get("credentials",{}).get("password",""))')
  [ -n "$PW" ] && break
  sleep 5
done

export PXS_URL=$(echo "$CRED" | python3 -c 'import json,sys;c=json.load(sys.stdin)["instance"]["credentials"];print(c.get("url") or "")')
export PXS_AUTH="$(echo "$CRED" | python3 -c 'import json,sys;c=json.load(sys.stdin)["instance"]["credentials"];print(c["username"]+":"+c["password"])')"
```

Sanity check — a JSON body with the cluster name and version means the endpoint, the account and your network path are all good:

```sh
curl -sS -u "$PXS_AUTH" "$PXS_URL"
```

If this times out, check in this order: (1) you are using `http://`, not `https://`; (2) your egress allows outbound
TCP 9200; (3) your data-plane egress IP is the one that was whitelisted at claim time — it can differ from the IP
you claimed with, because egress addresses vary by destination port. To re-check and add it:

```sh
MYIP=$(curl -fsSL 'https://zero.polardbx.com/api/v1/pxsearch/echo-ip' | python3 -c 'import json,sys;print(json.load(sys.stdin)["ip"])')
curl -fsSL -X PATCH "https://zero.polardbx.com/api/v1/pxsearch/instances/$ASSIGN/whitelist" \
  -H "x-pxz-token: $SESSION" -H 'Content-Type: application/json' -d "{\"whitelistIp\":\"$MYIP\"}"
```

## Create an index

`knn` must be enabled **at index creation time** — you cannot turn it on later. Attach a Chinese analyzer to text
fields and declare `knn_vector` for embeddings. `number_of_replicas: 1` is safe: a claimed cluster has at least
two data nodes, so the replica shard has somewhere to land and health reaches `green`.

```sh
curl -sS -u "$PXS_AUTH" -XPUT "$PXS_URL/docs" -H 'Content-Type: application/json' -d '{
  "settings": { "index": { "knn": true, "number_of_shards": 1, "number_of_replicas": 1 } },
  "mappings": { "properties": {
    "title":   { "type": "text", "analyzer": "ik_max_word" },
    "content": { "type": "text", "analyzer": "ik_max_word" },
    "embedding": {
      "type": "knn_vector", "dimension": 4,
      "method": { "name": "hnsw", "engine": "faiss", "space_type": "l2" }
    }
  } }
}'
```

## Load data

`_bulk` is NDJSON: one JSON object per line, and the body **must end with a newline**:

```sh
curl -sS -u "$PXS_AUTH" "$PXS_URL/docs/_bulk" -H 'Content-Type: application/x-ndjson' --data-binary $'
{"index":{"_id":"1"}}
{"title":"PolarDB-X 分布式数据库","content":"存储计算分离，兼容 MySQL 生态","embedding":[0.11,0.22,0.33,0.44]}
{"index":{"_id":"2"}}
{"title":"向量检索入门","content":"kNN 与 HNSW 图索引的基本原理","embedding":[0.10,0.20,0.35,0.40]}
'
curl -sS -u "$PXS_AUTH" -XPOST "$PXS_URL/docs/_refresh"
```

## Full-text search

```sh
curl -sS -u "$PXS_AUTH" "$PXS_URL/docs/_search?pretty" -H 'Content-Type: application/json' -d '{
  "query": { "match": { "content": "分词 打分" } },
  "highlight": { "fields": { "content": {} } }
}'
```

## Vector kNN and hybrid search

```sh
# pure vector kNN
curl -sS -u "$PXS_AUTH" "$PXS_URL/docs/_search?pretty" -H 'Content-Type: application/json' -d '{
  "size": 3, "query": { "knn": { "embedding": { "vector": [0.10,0.21,0.34,0.42], "k": 3 } } }
}'

# hybrid: full-text + vector, scores added via bool.should (tune the boosts per workload)
curl -sS -u "$PXS_AUTH" "$PXS_URL/docs/_search?pretty" -H 'Content-Type: application/json' -d '{
  "size": 3, "query": { "bool": { "should": [
    { "match": { "content": { "query": "向量 检索", "boost": 1.0 } } },
    { "knn": { "embedding": { "vector": [0.10,0.21,0.34,0.42], "k": 3, "boost": 2.0 } } }
  ] } }
}'
```

## Dashboards (web console)

The credentials response also carries a `dashboardUrl`. Open it in a browser and sign in with the same
username/password to get:

- **Dev Tools** — a console for running the REST queries above interactively
- **Discover** — browse documents and field distributions
- **Visualize** — build charts and dashboards

## Release

Hand the whole cluster back (**every index and document is destroyed**):

```sh
curl -fsSL -X DELETE "https://zero.polardbx.com/api/v1/pxsearch/instances/$ASSIGN" -H "x-pxz-token: $SESSION"
```

Doing nothing has the same effect once the assignment expires.

## Errors

| Message or symptom | What to do |
|---|---|
| `you already hold the maximum number of PXSearch instances` | release the old one first (DELETE above) |
| `your network has reached its PXSearch instance quota` | others behind the same egress IP count too; wait for one to expire or use another network |
| `PXSearch is unavailable or the warm pool is empty` | Search is in invitational preview; retry in a few minutes |
| `instance still provisioning` | credentials are not ready yet; keep polling `/credentials` |
| `401 Unauthorized` on the cluster | the password is wrong or truncated — a 401 means the network path is fine, so re-fetch `/credentials` and check the credentials, not the whitelist |
| connection times out | you used `https://` instead of `http://`, outbound TCP 9200 is blocked, or your egress IP is not whitelisted — look it up via `/pxsearch/echo-ip` and PATCH the whitelist |
| `index_not_found_exception` | create the index before writing or searching |
| `illegal_argument_exception` on knn query | `index.knn` was not enabled at creation time; recreate the index |