Valkey: 搜尋與 JSON
使用 Valkey 搜尋模組儲存及查詢 JSON 文件
👋 歡迎瀏覽 Stackhero 文件!
Stackhero 提供即開即用的 Valkey cloud 方案,帶來多項優勢,包括:
- 已包含
Valkey Admin網頁管理介面。- 無限訊息大小及傳輸量。
- 一鍵輕鬆完成更新。
- 以專屬私有基礎設施提供最佳效能及強大安全性。
節省時間,簡化您的工作流程:只需 5 分鐘即可體驗 Stackhero 的 Valkey cloud hosting 方案!
您在 Stackhero 上的 Valkey 實例已預載由 Valkey 專案維護的重要模組。這些模組讓 Valkey 不僅僅是一個快取:您可以原生儲存 JSON 文件、為資料建立索引,並執行標籤(tag)、數值、文字及向量查詢,無需額外管理獨立的資料庫。
目前有三個模組可用,全部已包含在您的方案內,並採用與 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後,搜尋結果可能會有幾秒鐘不完整,直到索引建立完成。 - 所有模組指令皆已啟用。 您的服務可使用每個模組的所有指令,無任何限制。
如欲進一步探索向量相似度、語意搜尋或檢索增強生成(retrieval-augmented generation, RAG),請參閱 向量搜尋指南。