唯杰地图 logo唯杰地图
VJMAP
EN

键值数据存储 (KV)

更新于 2026-04-25约 9 分钟
.md

分类代号:C.8 本章共 5 个接口

vjmap 内置了一个按工作区隔离的 KV 数据表(SQLite),用来存用户配置、缩略图、缓存数据等零碎东西。"零碎"并不代表"不好用"——二开里非常常用,比如存每个用户的图层可见性、自定义地图标注等。

存储位置:后端 data/customData.db。
自动前缀:所有用户可见 key 都加了隐形 data_ 前缀,本 SDK 已屏蔽此细节。
TTL:可选过期时间(秒),到期自动清理。
批量 key 分隔符:路径里 ;;(双分号)分隔多个 key。


快速索引

序号 SDK 方法 URL
53 get_custom_data / getCustomData GET /api/v1/service/data/{key}
54 save_custom_data / saveCustomData POST /api/v1/service/data/{key}
55 delete_custom_data / deleteCustomData DELETE /api/v1/service/data/{key}
56 save_multiple_custom_data / saveMultipleCustomData POST /api/v1/service/datas
57 get_custom_data_keys / getCustomDataKeys GET /api/v1/service/datakeys?prefix=

53 · 获取值 data/{key} GET

查询参数

字段 取值 说明
retDataType "" / "value" / "prop" 默认返回 {data, prop};value 只要 data;prop 只要 prop
contentType "" / "image" image 时后端把 base64 dataURL 解出,直接返回 PNG 二进制(不是 JSON)

批量:key 路径段用 ;; 拼接多 key,SDK 传字符串列表即可。

响应

  • 存在:{ "status": "ok", "data": <value>, "prop": <prop> }
  • 不存在:{ "status": "keyNoExist" }(不是 404)
  • 批量:{ "values": [...], "props": [...], "status": [...] }

实采

// get_custom_data.json
{
  "data": "hello-vjmap",
  "prop": "text/plain",
  "status": "ok"
}
// get_missing.json —— 一定要判断 status
{ "status": "keyNoExist" }

Python

d = svc.get_custom_data("myproj/theme")
if d["status"] == "keyNoExist":
    ...
else:
    theme = d["data"]

Node.js

const d = await svc.getCustomData('myproj/theme');
if (d.status === 'keyNoExist') { /* ... */ }

批量读

svc.get_custom_data(["a", "b"])
# { "values": ["va","vb"], "props":["pa","pb"], "status":["ok","ok"] }

54 · 保存值 data/{key} POST

查询参数

字段 说明
ttl 秒;到点清除。省略或 0 = 长期

Body 两种写法

  1. JSON:{"value": "...", "prop": "..."};prop 可存元数据(MIME、扩展字段)
  2. Raw:直接把文件二进制 POST 上去,作为 value 字段存(SDK 里叫 raw_body / rawBody)

响应(实采)

{
  "data": "nb_kv_a_1776832185",
  "status": "ok"
}

Python

svc.save_custom_data("myproj/theme",
                    value='{"mode":"dark"}',
                    prop="application/json")

# 带 TTL
svc.save_custom_data("tmp_token",
                    value="eyJ...", ttl=3600)

# Raw bytes
svc.save_custom_data("user_avatar_42",
                    raw_body=open("avatar.png","rb").read())

Node.js

await svc.saveCustomData('myproj/theme', {
  value: JSON.stringify({ mode: 'dark' }),
  prop: 'application/json',
});

await svc.saveCustomData('tmp_token', { value: tokenStr, ttl: 3600 });

55 · 删除值 data/{key} DELETE

查询参数

字段 说明
isPrefix "true" 时把 key 当前缀,批量清除;否则只删单条

响应

  • 单条(实采):{"data":"nb_kv_a_...","status":"ok"}
  • 前缀(实采):{"data":"nb_prefix_...","isPrefix":true,"status":"ok"}

Python

svc.delete_custom_data("myproj/theme")

# 前缀批量
svc.delete_custom_data("myproj/user42/", is_prefix=True)

# 列表批量(走 ;; 分隔)
svc.delete_custom_data(["a", "b", "c"])

56 · 批量存值 datas POST

URL:POST /api/v1/service/datas

Body

[{"key":..,"value":..,"prop":..,"ttl":"60"}],注意 ttl 是字符串秒数。

响应(实采)

{ "status": ["ok"] }

Python

svc.save_multiple_custom_data([
    {"key": "cfg/a", "value": "1"},
    {"key": "cfg/b", "value": "2", "ttl": "3600"},
])

Node.js

await svc.saveMultipleCustomData([
  { key: 'cfg/a', value: '1' },
  { key: 'cfg/b', value: '2', ttl: '3600' },
]);

57 · 按前缀列键 datakeys GET

查询参数

字段 说明
prefix 前缀(自动加 data_)
retDataType value / prop / valueprop —— 同时取出值,省一次往返
isSys true 时返回带 data_ 内部前缀的系统键(仅 root 场景)

响应

  • 仅 keys(实采):
{ "keys": ["nb_kv_a_1776832185", "nb_kv_b_1776832185"] }
  • 带值(retDataType=valueprop,实采):
{
  "keys":   ["nb_kv_a_1776832185", "nb_kv_b_1776832185"],
  "props":  ["text/plain",          "bp-1"],
  "values": ["hello-vjmap",         "batch-1"],
  "status": ["ok",                  "ok"]
}

Python

keys = svc.get_custom_data_keys(prefix="myproj/")["keys"]

# 同时取值
bundle = svc.get_custom_data_keys(prefix="myproj/", ret_data_type="valueprop")
for k, v, p in zip(bundle["keys"], bundle["values"], bundle["props"]):
    print(k, v, p)

最佳实践

  1. 前缀分层:用 //: 建立命名空间,如 myproj/user42/tool_state。这样前缀批量删除、列出都方便。
  2. 大文件不要存 KV:value 单条一般 < 1 MB;大图/DWG 用 /map/uploadmap 或独立对象存储。
  3. TTL 清理:用 ttl 让后端帮忙过期;别自己写 crontab。
  4. keyNoExist ≠ 错误:200 正常响应里 status == "keyNoExist" 表示没值,而不是失败。

这篇文档有帮助吗?