Chúng tôi sẽ ra mắt Upstash Redis Search trong 1-2 tuần tới nhưng tôi muốn chia sẻ một số suy nghĩ ban đầu về những gì chúng tôi đang xây dựng và lý do khiến tôi hào hứng với nó.
Tại sao chúng tôi xây dựng cái này
Chúng tôi đã tham gia không gian tìm kiếm từ năm 2024, bắt đầu với Upstash Vector. Vector cho phép mọi người triển khai tìm kiếm ngữ nghĩa và sau đó chúng tôi tăng gấp đôi không gian sản phẩm này bằng Upstash Search.
Ví dụ:đây là tweet ra mắt của chúng tôi từ năm 2025 để thông báo về Upstash Search, giải pháp tìm kiếm ngữ nghĩa dựa trên vectơ của chúng tôi 👇

Và tôi nghĩ chúng tôi có thể làm tốt hơn nữa và phát triển dựa trên những bài học từ Tìm kiếm.
Chúng tôi khá không hài lòng với hầu hết các nhà cung cấp dịch vụ tìm kiếm hiện có. Đối với cá nhân tôi, không có cái nào trong số chúng thực sự phù hợp với không gian serverless. Nhiều đến mức tôi thậm chí còn xây dựng ứng dụng tìm kiếm của riêng mình dựa trên AWS Cloudsearch vào năm 2023 💀
Điều chúng tôi muốn là thứ:
- Sống trong Redis vì Redis hoạt động nhanh
- Hoạt động với SDK Upstash Redis
- An toàn loại 100%
- Đủ nhanh để tìm kiếm theo thời gian thực khi bạn nhập
Vì vậy chúng tôi đang xây dựng nó.
Tiện ích mở rộng đầu tiên của chúng tôi ngoài API Redis
Đây là một vấn đề lớn đối với chúng tôi. Cho đến bây giờ, @upstash/redis là sự ánh xạ gần 1:1 của các lệnh Redis. Tìm kiếm là tiện ích mở rộng đầu tiên của chúng tôi ngoài điều đó.
Chúng tôi đang sử dụng Tantivy, một công cụ tìm kiếm toàn văn bản được viết bằng Rust lấy cảm hứng từ Apache Lucene. Nó nhanh. Thực sự nhanh chóng. Và nó cung cấp cho chúng tôi tất cả những thứ cơ bản mà chúng tôi cần như mã thông báo, bắt nguồn, đối sánh mờ, truy vấn cụm từ và tính điểm BM25.
Mục tiêu là làm cho điều này trở nên tự nhiên đối với SDK và chính Upstash Redis. Nếu bạn đang sử dụng @upstash/redis ngày nay, việc thêm tìm kiếm sẽ giống như một tiện ích mở rộng tự nhiên chứ không phải là một sản phẩm riêng biệt.
Trình tạo lược đồ an toàn loại
Một điều tôi thực sự hài lòng là trình tạo lược đồ mới. Chúng tôi xác định các trường có thể tìm kiếm bằng API giống zod:
import { Redis, s } from "@upstash/redis";
const redis = Redis.fromEnv();
const schema = s.object({
name: s.string(),
description: s.string(),
sku: s.string().noTokenize(),
brand: s.string().noStem(),
price: s.number(),
inStock: s.boolean(),
});
const products = await redis.search.createIndex({
name: "products",
dataType: "json",
prefix: "product:",
schema,
});
.noTokenize() và .noStem() các phương thức cho phép chúng tôi kiểm soát cách xử lý văn bản:
- Mã thông báo chia văn bản thành các từ có thể tìm kiếm được. Phù hợp với ngôn ngữ tự nhiên nhưng lại phá vỡ những thứ như SKU (
SKU-12345-BLKtrở thành["SKU", "12345", "BLK"]). Tắt tính năng này đối với mã, email và UUID. - Có gốc chuyển các từ về dạng gốc để "running" khớp với "run". Tắt tính năng này cho tên thương hiệu và danh từ riêng mà chúng tôi muốn đối sánh chính xác.
Lược đồ cung cấp cho chúng ta suy luận kiểu đầy đủ về các truy vấn. Nếu chúng ta cố gắng truy vấn một trường không tồn tại, TypeScript sẽ bắt được nó. Chúng tôi đang giữ cú pháp lược đồ rất gần với cú pháp zod để có cảm giác quen thuộc khi sử dụng.
Truy vấn nguyên thủy
Chúng tôi sắp ra mắt năm toán tử chính mà chúng tôi cho rằng sẽ đáp ứng hầu hết các trường hợp sử dụng tìm kiếm:
$smart để kết hợp thông minh
Với toán tử $smart, chúng tôi tự động áp dụng tính năng khớp thông minh. Toán tử này chỉ hoạt động™ và là cách tốt nhất cho người mới bắt đầu.
await products.query({
filter: {
name: { $smart: "wirless headphones" },
},
}); Dưới mui xe, cái này chạy:
- Đối sánh cụm từ chính xác (mức tăng cao nhất) - Các tài liệu có "tai nghe không dây" liền kề và theo thứ tự
- Cụm từ có độ dốc (tăng trung bình) - Tài liệu trong đó các từ xuất hiện theo thứ tự nhưng không liền kề (ví dụ:tai nghe bose không dây)
- Điều khoản phù hợp (tăng trung bình) - Tài liệu chứa tất cả các điều khoản, đơn hàng bất kỳ
- Kết hợp mờ (không tăng tốc) - Tài liệu có lỗi chính tả như "tai nghe có dây"
- Tiền tố mờ ở từ cuối cùng (không tăng tốc) - Dành cho trường hợp tìm kiếm khi bạn nhập
Điểm số được kết hợp để có được kết quả phù hợp nhất. Đối với hầu hết các hộp tìm kiếm, đây thực sự là tất cả những gì bạn cần. Tất nhiên, bạn có thể tự triển khai toán tử này và thử nghiệm các cài đặt vì nó được xây dựng trên các toán tử nguyên thủy khác bên dưới.
$eq cho sự bình đẳng chính xác
Đối với các trường mà chúng tôi muốn đối sánh chính xác:
await products.query({
filter: {
name: { $eq: "wireless headphones" },
price: { $eq: 200 },
},
}); $phrase để khớp cụm từ
Khi chúng ta cần các từ xuất hiện liền kề và theo thứ tự:
await products.query({
filter: { description: { $phrase: "noise cancelling" } },
});
Chúng ta cũng có thể thêm slop để cho phép các từ ở giữa:
await products.query({
filter: {
description: {
$phrase: { value: "wireless headphones", slop: 2 },
},
},
}); $fuzzy về khả năng chịu lỗi đánh máy
Để khớp mờ với dung sai lỗi chính tả có thể định cấu hình (ví dụ:2 lỗi chính tả):
await products.query({
filter: { name: { $fuzzy: "headphonse", distance: 2 } },
}); $regex để khớp mẫu
Khi chúng ta cần các mẫu biểu thức chính quy:
await products.query({
filter: { sku: { $regex: "SKU-[0-9]{5}-.*" } },
});
Một điều cần lưu ý:biểu thức chính quy hoạt động tốt nhất trên các trường có .noStem() vì văn bản có gốc sẽ không khớp với các mẫu dự kiến.
Thúc đẩy các trường cụ thể
Chúng ta có thể áp dụng các mức tăng để tăng trọng số cho một số trận đấu nhất định:
await products.query({
filter: {
$and: [
{ name: { $smart: "wireless", $boost: 2 } },
{ description: { $smart: "wireless" } },
],
},
}); Điều này làm cho kết quả trùng khớp tên có giá trị gấp đôi so với kết quả trùng khớp mô tả. Điều này hữu ích khi chúng tôi muốn các kết quả phù hợp tiêu đề xếp hạng cao hơn các kết quả phù hợp nội dung.
Tiếp theo là gì
Tất cả những điều tôi đưa vào bài viết này vẫn có thể thay đổi. Chúng tôi vẫn đang hoàn thiện các khía cạnh và viết tài liệu. Sẽ ra mắt chính thức sau 1-2 tuần nữa.
Nhưng tôi nghĩ thật tuyệt khi chúng ta có thể nhìn nhau lần đầu tiên 👀
Một số điều chúng ta có thể khám phá sau khi ra mắt:
- Tích hợp tìm kiếm vectơ (tìm kiếm kết hợp ngữ nghĩa + từ khóa)
- Tự động hoàn thành và đề xuất
Nếu bạn muốn có quyền truy cập sớm hoặc có thắc mắc, hãy liên hệ với tôi @joshtriedcoding.
Cảm ơn đã đọc 🙌