Valkey: 搜尋與 JSON
使用 Valkey 搜尋模組儲存與查詢 JSON 文件
👋 歡迎來到 Stackhero 文件中心!
Stackhero 提供即時可用的 Valkey cloud 解決方案,帶來多項優勢,包括:
- 內建
Valkey Admin網頁管理介面。- 無限制的訊息大小與傳輸量。
- 一鍵輕鬆完成更新。
- 以專屬私有基礎架構提供最佳效能與強大安全性。
節省時間、簡化您的工作流程:只需 5 分鐘即可體驗 Stackhero 的 Valkey cloud hosting 解決方案!
您在 Stackhero 上的 Valkey 實例已包含由 Valkey 專案維護的核心模組。這些模組讓 Valkey 不僅僅是快取:您可以原生儲存 JSON 文件、建立資料索引,並執行標籤、數值、文字與向量查詢,無需額外管理獨立的資料庫。
目前有三個模組可用,皆已包含於您的方案中,並採用與 Valkey 相同的 BSD 3-Clause 寬鬆授權:
- JSON(
JSON.*指令):支援 JSONPath,可儲存與更新結構化 JSON 文件。您可以直接讀取或修改單一欄位,針對小幅變更無需重寫整份文件。 - Search(
FT.*指令):可進行次級索引、標籤、數值、全文查詢,以及向量相似度搜尋。 - Bloom(
BF.*指令):利用 Bloom filter 高效判斷「這個資料是否已經出現過?」適用於大量資料集,且記憶體用量極低。
啟用模組
模組預設為關閉,因此現有服務會維持原有行為,直到您主動啟用。
- 於 Stackhero 控制台 開啟您的服務。
- 前往服務設定頁面。
- 在 Modules 區段,勾選您要啟用的模組。
- 儲存變更。
Valkey 會重新啟動以載入所選模組,通常僅需數秒。
若您已使用某個模組儲存資料(例如 JSON 文件或 Bloom filter),請務必保持該模組啟用。Valkey 無法在缺少原始模組的情況下讀取這些資料。若停用該模組,服務將無法順利重啟。
您可隨時檢查目前已載入哪些模組:
valkey-cli -u "rediss://default:<yourPassword>@<XXXXXX>.stackhero-network.com:<PORT_TLS>" MODULE LIST
儲存 JSON 文件
您可以直接以 JSON 格式原生儲存結構化文件,無需序列化為字串:
JSON.SET product:1 $ '{"name":"Espresso machine","brand":"Bianca","price":459,"stock":12}'
讀取或更新單一欄位快速、具原子性,且於伺服器端處理:
JSON.GET product:1 $.price
# "[459]"
JSON.NUMINCRBY product:1 $.stock -1
# "[11]"
這種方式讓您無需每次更新都在應用程式端抓取與解析整份文件。例如,庫存數量遞減現在只需一個原子操作,避免競爭條件與額外程式碼。
JSON.* 指令集與 RedisJSON API 相容,因此大多數 Valkey 與 Redis 客戶端皆可直接使用。
建立索引與搜尋
只需建立一次索引,Valkey 會自動維護所有符合前綴的 key,即使是在建立索引前已存在的 key 也會納入:
FT.CREATE productsIndex
ON HASH
PREFIX 1 product:
SCHEMA
name TEXT
brand TAG
price NUMERIC
您可以透過強大的搜尋指令查詢已索引的資料:
# 標籤精確比對
FT.SEARCH productsIndex "@brand:{Bianca}"
# 數值範圍查詢
FT.SEARCH productsIndex "@price:[0 500]"
# 複合查詢
FT.SEARCH productsIndex "@brand:{Bianca} @price:[0 500]"
# 依名稱全文搜尋
FT.SEARCH productsIndex "espresso"
您也可以使用 FT.AGGREGATE 在同一索引上進行聚合查詢。FT.INFO 指令可查詢索引狀態,包括背景索引作業的進度。
JSON 文件同樣可被索引。啟用 JSON 模組後,您可在 schema 中使用 ON JSON 與 JSONPath 表達式。
範例:在 Node.js 使用 Valkey 搜尋
Valkey 採用與 Redis 相同的協定,因此任何 Redis 客戶端皆可相容。您可搭配官方 node-redis client 使用下列範例:
import { createClient, SCHEMA_FIELD_TYPE } from 'redis';
const client = createClient({ url: process.env.STACKHERO_VALKEY_URL_TLS });
await client.connect();
// 啟動時建立索引(僅需一次)
try {
await client.ft.create(
'productsIndex',
{
name: SCHEMA_FIELD_TYPE.TEXT,
brand: SCHEMA_FIELD_TYPE.TAG,
price: SCHEMA_FIELD_TYPE.NUMERIC
},
{ ON: 'HASH', PREFIX: 'product:' }
);
} catch (error) {
if (!error.message.includes('Index already exists')) {
throw error;
}
}
await client.hSet('product:1', { name: 'Espresso machine', brand: 'Bianca', price: '459' });
const results = await client.ft.search('productsIndex', '@brand:{Bianca} @price:[0 500]');
console.log(results.total, results.documents);
await client.quit();
範例:在 Python 使用 Valkey 搜尋
您可以使用 redis-py client 操作 Valkey 搜尋功能:
import os
import redis
from redis.commands.search.field import TextField, TagField, NumericField
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query
r = redis.from_url(os.environ['STACKHERO_VALKEY_URL_TLS'], decode_responses=True)
# 啟動時建立索引(僅需一次)
try:
r.ft('productsIndex').create_index(
(TextField('name'), TagField('brand'), NumericField('price')),
definition=IndexDefinition(prefix=['product:'], index_type=IndexType.HASH),
)
except redis.ResponseError as error:
if 'Index already exists' not in str(error):
raise
r.hset('product:1', mapping={'name': 'Espresso machine', 'brand': 'Bianca', 'price': 459})
results = r.ft('productsIndex').search(Query('@brand:{Bianca} @price:[0 500]'))
print(results.total, results.docs)
實用資訊
- 搜尋模組提供精簡且專注的指令集:
FT.CREATE、FT.SEARCH、FT.AGGREGATE、FT.INFO、FT.DROPINDEX及FT._LIST。這些指令可高效處理標籤、數值、文字與向量查詢。若您的應用需要進階全文功能(如拼字檢查、同義詞或建議字典),可參考 Redis 查詢引擎 以獲得更多功能。 - 索引為每個資料庫獨立建立,僅在該資料庫內可見與查詢。 例如,在資料庫 3 建立的索引,僅能在資料庫 3 查詢。這是 Valkey 相較於 Redis 資料庫選擇 的延伸,後者僅支援在資料庫 0 建立索引。
- 索引會佔用您方案的記憶體,與資料本身相同。建立索引後,您可於 Prometheus 指標 監控
used_memory。 - 現有 key 的索引會於背景執行。 執行
FT.CREATE後,搜尋結果可能在數秒內尚未完整,待索引建置完成即可。 - 所有模組指令皆已啟用。 您的服務可使用所有模組的所有指令,無任何限制。
若您想進一步探索向量相似度、語意搜尋或檢索增強生成(RAG),請參閱 向量搜尋指南。