1. Tổng quan
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách thêm các tính năng tìm kiếm mạnh mẽ vào ứng dụng bằng cách sử dụng tính năng tìm kiếm vectơ tương đồng trên Firestore. Bạn sẽ triển khai tính năng tìm kiếm ngữ nghĩa cho một ứng dụng ghi chú được viết bằng Swift và SwiftUI.
Kiến thức bạn sẽ học được
- Cách cài đặt tiện ích Tìm kiếm vectơ với Firestore để tính toán các mục nhúng vectơ.
- Cách gọi Firebase Cloud Functions từ một ứng dụng Swift.
- Cách lọc trước dữ liệu dựa trên người dùng đã đăng nhập.
Những gì bạn cần có
- Xcode 15.3
- Mã mẫu của lớp học lập trình. Bạn sẽ tải tệp này xuống trong một bước sau của lớp học lập trình.
2. Tạo và thiết lập dự án Firebase
Để sử dụng tiện ích Tìm kiếm vectơ Firebase, bạn cần có một dự án Firebase. Trong phần này của lớp học lập trình, bạn sẽ tạo một dự án Firebase mới và kích hoạt các dịch vụ bắt buộc như Cloud Firestore và Xác thực Firebase.
Tạo dự án Firebase
- Đăng nhập vào Firebase
- Trong bảng điều khiển của Firebase, hãy nhấp vào Thêm dự án, sau đó đặt tên cho dự án là Firestore Vector Search Lab (Phòng thí nghiệm tìm kiếm vectơ Firebase)
- Nhấp vào các tuỳ chọn tạo dự án. Chấp nhận các điều khoản của Firebase nếu được nhắc.
- Trên màn hình Google Analytics, hãy bỏ đánh dấu hộp Bật Google Analytics cho dự án này vì bạn sẽ không sử dụng Analytics cho ứng dụng này.
- Cuối cùng, hãy nhấp vào Tạo dự án.
Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu về các dự án Firebase.
Nâng cấp gói giá Firebase của bạn
Để sử dụng Tiện ích Firebase và các dịch vụ đám mây cơ bản của tiện ích, dự án Firebase của bạn cần sử dụng gói giá trả theo mức sử dụng (Blaze), tức là dự án được liên kết với một tài khoản Thanh toán trên đám mây.
- Tài khoản Cloud Billing cần có một phương thức thanh toán, chẳng hạn như thẻ tín dụng.
- Nếu bạn mới sử dụng Firebase và Google Cloud, hãy kiểm tra xem bạn có đủ điều kiện nhận khoản tín dụng 300 USD và tài khoản dùng thử miễn phí trên Cloud Billing hay không.
- Nếu bạn tham gia lớp học lập trình này trong một sự kiện, hãy hỏi người tổ chức xem có khoản tín dụng Google Cloud nào không.
Để nâng cấp dự án lên gói Blaze, hãy làm theo các bước sau:
- Trong bảng điều khiển của Firebase, hãy chọn nâng cấp gói.
- Chọn gói Blaze. Làm theo hướng dẫn trên màn hình để liên kết tài khoản thanh toán Cloud với dự án của bạn.
Nếu cần tạo một tài khoản thanh toán Cloud trong quá trình nâng cấp này, bạn có thể phải quay lại quy trình nâng cấp trong bảng điều khiển của Firebase để hoàn tất quá trình nâng cấp.
Bật và thiết lập các sản phẩm Firebase trong bảng điều khiển
Ứng dụng bạn đang tạo sử dụng một số sản phẩm Firebase có sẵn cho các ứng dụng của Apple:
- Xác thực Firebase để dễ dàng cho phép người dùng đăng nhập vào ứng dụng của bạn.
- Cloud Firestore để lưu dữ liệu có cấu trúc lên đám mây và nhận thông báo tức thì khi dữ liệu thay đổi.
- Quy tắc bảo mật của Firebase để bảo vệ cơ sở dữ liệu của bạn.
Một số sản phẩm trong số này cần cấu hình đặc biệt hoặc cần được bật bằng cách sử dụng bảng điều khiển của Firebase.
Bật tính năng xác thực ẩn danh cho tính năng Xác thực Firebase
Ứng dụng này sử dụng tính năng xác thực ẩn danh để cho phép người dùng bắt đầu sử dụng ứng dụng mà không cần tạo tài khoản trước. Điều này giúp quá trình làm quen trở nên dễ dàng hơn. Để tìm hiểu thêm về quy trình xác thực ẩn danh (và cách nâng cấp lên tài khoản được đặt tên), hãy xem Các phương pháp hay nhất để xác thực ẩn danh.
- Trong bảng điều khiển bên trái của bảng điều khiển Firebase, hãy nhấp vào Tạo > Xác thực. Sau đó, hãy nhấp vào Bắt đầu.
- Bạn hiện đang ở trang tổng quan về Xác thực, nơi bạn có thể xem những người dùng đã đăng ký, định cấu hình nhà cung cấp dịch vụ đăng nhập và quản lý chế độ cài đặt.
- Chọn thẻ Phương thức đăng nhập (hoặc nhấp vào đây để chuyển thẳng đến thẻ này).
- Nhấp vào Ẩn danh trong các tuỳ chọn nhà cung cấp, chuyển nút bật/tắt sang Bật, rồi nhấp vào Lưu.
Thiết lập Cloud Firestore
Ứng dụng Swift này sử dụng Cloud Firestore để lưu ghi chú.
Dưới đây là cách thiết lập Cloud Firestore trong dự án Firebase:
- Trong bảng điều khiển bên trái của Firebase, hãy mở rộng mục Build (Tạo) rồi chọn Firestore database (Cơ sở dữ liệu Firestore).
- Nhấp vào Tạo cơ sở dữ liệu.
- Đặt Mã nhận dạng cơ sở dữ liệu thành
(default)
. - Chọn một vị trí cho cơ sở dữ liệu, rồi nhấp vào Tiếp theo.
Đối với ứng dụng thực tế, bạn nên chọn một vị trí gần với người dùng. - Nhấp vào Bắt đầu ở chế độ thử nghiệm. Đọc tuyên bố từ chối trách nhiệm về các quy tắc bảo mật.
Trong phần sau của lớp học lập trình này, bạn sẽ thêm Quy tắc bảo mật để bảo mật dữ liệu của mình. Không phân phối hoặc tiết lộ ứng dụng công khai khi chưa thêm Quy tắc bảo mật cho cơ sở dữ liệu của bạn. - Nhấp vào Tạo.
Thiết lập Cloud Storage cho Firebase
Ứng dụng web sử dụng Cloud Storage cho Firebase để lưu trữ, tải lên và chia sẻ ảnh.
Sau đây là cách thiết lập Cloud Storage cho Firebase trong dự án Firebase:
- Trong bảng điều khiển bên trái của Firebase, hãy mở rộng mục Bản dựng rồi chọn Bộ nhớ.
- Nhấp vào Bắt đầu.
- Chọn vị trí cho bộ chứa Bộ nhớ mặc định.
Các bộ chứa trongUS-WEST1
,US-CENTRAL1
vàUS-EAST1
có thể tận dụng cấp "Luôn miễn phí" cho Google Cloud Storage. Các bộ chứa ở tất cả các vị trí khác tuân theo mức giá và mức sử dụng của Google Cloud Storage. - Nhấp vào Bắt đầu ở chế độ thử nghiệm. Đọc tuyên bố từ chối trách nhiệm về các quy tắc bảo mật.
Trong phần sau của lớp học lập trình này, bạn sẽ thêm các quy tắc bảo mật để bảo mật dữ liệu của mình. Không không phân phối hoặc tiết lộ ứng dụng công khai khi chưa thêm Quy tắc bảo mật cho bộ chứa Storage. - Nhấp vào Tạo.
3. Kết nối ứng dụng di động
Trong phần này của lớp học lập trình, bạn sẽ tải mã nguồn cho một ứng dụng ghi chú đơn giản xuống và kết nối ứng dụng đó với dự án Firebase mà bạn vừa tạo.
Tải ứng dụng mẫu xuống
- Truy cập vào https://github.com/FirebaseExtended/codelab-firestore-vectorsearch-ios và nhân bản kho lưu trữ vào máy cục bộ của bạn
- Mở dự án Notes.xcodeproj trong Xcode
Kết nối ứng dụng với dự án Firebase
Để ứng dụng của bạn có thể truy cập vào các dịch vụ của Firebase, bạn cần thiết lập ứng dụng trong bảng điều khiển của Firebase. Bạn có thể kết nối nhiều ứng dụng khách với cùng một dự án Firebase, ví dụ: nếu tạo một ứng dụng Android hoặc ứng dụng web, bạn nên kết nối các ứng dụng đó với cùng một dự án Firebase.
Để tìm hiểu thêm về các dự án Firebase, hãy xem bài viết Tìm hiểu về các dự án Firebase.
- Trong bảng điều khiển của Firebase, hãy chuyển đến trang tổng quan của dự án Firebase.
- Nhấp vào biểu tượng iOS+ để thêm ứng dụng iOS.
- Trong màn hình Thêm Firebase vào ứng dụng Apple của bạn, hãy chèn mã gói từ dự án Xcode (com.google.firebase.codelab.Notes).
- Nếu muốn, bạn có thể nhập biệt hiệu ứng dụng (Ghi chú dành cho iOS).
- Nhấp vào Đăng ký ứng dụng để chuyển sang bước tiếp theo.
- Tải tệp GoogleServices-Info.plist xuống.
- Kéo GoogleServices-Info.plist vào thư mục Notes (Ghi chú) của dự án Xcode. Một cách hữu hiệu để thực hiện việc này là thả tệp vào bên dưới tệp Assets.xcAsset.
- Chọn Copy items if needed (Sao chép mục nếu cần), đảm bảo rằng mục tiêu Notes (Ghi chú) được chọn trong Add to targets (Thêm vào mục tiêu) rồi nhấp vào Finish (Hoàn tất).
- Trong bảng điều khiển Firebase, giờ đây, bạn có thể nhấp vào phần còn lại của quy trình thiết lập: mẫu bạn đã tải xuống ở đầu phần này đã cài đặt SDK Firebase Apple và thiết lập quá trình khởi chạy. Bạn có thể kết thúc quá trình bằng cách nhấp vào Tiếp tục đến bảng điều khiển.
Chạy ứng dụng
Giờ là lúc thử nghiệm ứng dụng!
- Quay lại Xcode, hãy chạy ứng dụng trên Trình mô phỏng iOS. Trong trình đơn thả xuống Run Destinations (Đích chạy), trước tiên, hãy chọn một trong các Trình mô phỏng iOS.
- Sau đó, nhấp vào nút Run (Chạy) hoặc nhấn tổ hợp phím ⌘ + R
- Sau khi ứng dụng khởi chạy thành công trên Trình mô phỏng, hãy thêm một vài ghi chú.
- Trong bảng điều khiển Firebase, hãy chuyển đến trình duyệt dữ liệu Firestore để bạn có thể thấy các tài liệu mới được tạo khi thêm ghi chú mới trong ứng dụng.
4. Cài đặt tiện ích Tìm kiếm vectơ bằng Firestore
Trong phần này của lớp học lập trình, bạn sẽ cài đặt tiện ích Vector Search với Firestore và định cấu hình tiện ích này theo yêu cầu của ứng dụng ghi chú mà bạn đang xử lý.
Bắt đầu cài đặt tiện ích
- Vẫn trong phần Firestore, hãy nhấp vào thẻ Extensions (Tiện ích).
- Nhấp vào Khám phá Trung tâm tiện ích.
- Nhập "vector" (vectơ).
- Nhấp vào "Tìm kiếm vectơ có tiện ích Firestore". Thao tác này sẽ đưa bạn đến trang chi tiết của tiện ích. Tại đây, bạn có thể đọc thêm về tiện ích, cách hoạt động, các dịch vụ Firebase mà tiện ích yêu cầu và cách định cấu hình tiện ích.
- Nhấp vào Cài đặt trong bảng điều khiển của Firebase.
- Bạn sẽ thấy danh sách tất cả dự án của mình.
- Chọn dự án bạn đã tạo ở bước đầu tiên của lớp học lập trình này.
Định cấu hình tiện ích
- Xem các API được bật và tài nguyên đã tạo.
- Bật các dịch vụ bắt buộc.
- Sau khi bật tất cả các dịch vụ, hãy nhấp vào Next (Tiếp theo).
- Xem lại quyền truy cập đã cấp cho tiện ích này.
- Định cấu hình tiện ích:
- Chọn Vertex AI làm LLM
- Đường dẫn bộ sưu tập: notes
- Giới hạn truy vấn mặc định: 3
- Tên trường nhập dữ liệu: text
- Tên trường đầu ra: nhúng
- Tên trường trạng thái:* *status*
- Nhúng tài liệu hiện có: Có
- Cập nhật tài liệu hiện có: Có
- Vị trí của Hàm trên đám mây: us-central1
- Nhấp vào Cài đặt tiện ích để hoàn tất quá trình cài đặt.
Quá trình này có thể mất vài phút. Trong khi chờ quá trình cài đặt hoàn tất, bạn có thể chuyển sang phần tiếp theo của hướng dẫn và đọc một số thông tin cơ bản về nội dung nhúng vectơ.
5. Thông tin khái quát
Trong khi chờ quá trình cài đặt hoàn tất, sau đây là một số thông tin cơ bản về cách hoạt động của tiện ích Tìm kiếm vectơ bằng Firestore.
Vectơ, Nhúng và Cơ sở dữ liệu vectơ là gì?
- Vectơ là các đối tượng toán học biểu thị độ lớn và hướng của một đại lượng. Chúng có thể được dùng để trình bày dữ liệu theo cách giúp việc so sánh và tìm kiếm dễ dàng hơn.
- Nội dung nhúng là các vectơ thể hiện ý nghĩa của một từ hoặc cụm từ. Chúng được tạo bằng cách huấn luyện mạng nơron trên một lượng lớn văn bản và tìm hiểu mối quan hệ giữa các từ.
- Cơ sở dữ liệu vectơ là cơ sở dữ liệu được tối ưu hoá để lưu trữ và tìm kiếm dữ liệu vectơ. Các vectơ này cho phép tìm kiếm hàng xóm gần nhất một cách hiệu quả, đây là quá trình tìm các vectơ tương tự nhất với một vectơ truy vấn nhất định.
Tính năng Tìm kiếm vectơ hoạt động như thế nào?
Tìm kiếm vectơ hoạt động bằng cách so sánh vectơ truy vấn với tất cả các vectơ trong cơ sở dữ liệu. Các vectơ tương tự nhất với vectơ truy vấn sẽ được trả về dưới dạng kết quả tìm kiếm.
Bạn có thể đo lường mức độ tương đồng giữa hai vectơ bằng nhiều chỉ số khoảng cách. Chỉ số khoảng cách phổ biến nhất là độ tương đồng về cosin, dùng để đo góc giữa hai vectơ.
6. Thử dùng tiện ích Tìm kiếm vectơ với Firestore
Trước khi sử dụng tiện ích Tìm kiếm vectơ bằng Firestore trong ứng dụng iOS mà bạn đã tải xuống trước đó trong lớp học lập trình này, bạn có thể dùng thử tiện ích này trong bảng điều khiển Firebase.
Đọc tài liệu
Tiện ích Firebase bao gồm cả tài liệu về cách hoạt động của các tiện ích này.
- Sau khi cài đặt xong tiện ích đó, hãy nhấp vào nút Get started (Bắt đầu).
- Hãy xem thẻ "Cách hoạt động của tiện ích này". Thẻ này giải thích:
- cách tính toán các phần nhúng cho tài liệu bằng cách thêm các phần nhúng đó vào bộ sưu tập
notes
, - cách truy vấn chỉ mục bằng cách gọi hàm có thể gọi
ext-firestore-vector-search-queryCallable
, - hoặc cách truy vấn chỉ mục bằng cách thêm tài liệu truy vấn vào tập hợp
_firestore-vector-search/index/queries
. - Tài liệu này cũng giải thích cách thiết lập hàm nhúng tuỳ chỉnh – điều này sẽ hữu ích nếu không có LLM nào mà tiện ích hỗ trợ đáp ứng yêu cầu của bạn và bạn muốn sử dụng một LLM khác để tính toán các phần nhúng.
- cách tính toán các phần nhúng cho tài liệu bằng cách thêm các phần nhúng đó vào bộ sưu tập
- Nhấp vào đường liên kết Trang tổng quan về Cloud Firestore để chuyển đến thực thể Firestore của bạn
- Chuyển đến tài liệu
_firestore-vector-search/index
. Bạn sẽ thấy thông báo cho biết tiện ích đã hoàn tất việc tính toán nội dung nhúng cho tất cả tài liệu ghi chú mà bạn đã tạo ở bước trước trong lớp học lập trình này. - Để xác minh điều này, hãy mở một trong các tài liệu ghi chú và bạn sẽ thấy một trường bổ sung có tên
embedding
thuộc loạivector<768>
, cũng như một trườngstatus
.
Tạo tài liệu mẫu
Bạn có thể tạo một tài liệu mới trong bảng điều khiển Firebase để xem tiện ích này hoạt động như thế nào.
- Vẫn trong trình duyệt dữ liệu Firestore, hãy chuyển đến bộ sưu tập
notes
rồi nhấp vào + Thêm tài liệu ở cột ở giữa. - Nhấp vào Tự động nhận dạng để tạo một mã tài liệu mới duy nhất.
- Thêm một trường có tên
text
thuộc loại chuỗi và dán một số văn bản vào trường value (giá trị). Điều quan trọng là văn bản này không phải là lorem ipsum hoặc một số văn bản ngẫu nhiên khác. Ví dụ: chọn một bài báo. - Nhấp vào Lưu.
- Hãy lưu ý cách tiện ích thêm trường trạng thái để cho biết đang xử lý dữ liệu.
- Sau giây lát, bạn sẽ thấy trường mới
embedding
có giá trịvector<768>
.
Thực hiện truy vấn
Tìm kiếm vectơ bằng tiện ích Firestore có một tính năng nhỏ tiện lợi cho phép bạn truy vấn chỉ mục tài liệu mà không cần kết nối ứng dụng.
- Trong mục Firestore của bảng điều khiển Firebase, hãy chuyển đến tài liệu
_firestore-vector-search/index
- Nhấp vào + Bắt đầu thu thập
- Tạo một bộ sưu tập con mới có tên là
queries
- Tạo một tài liệu mới và đặt trường
query
thành văn bản xuất hiện trong một trong các tài liệu của bạn. Cách này hoạt động hiệu quả nhất đối với các truy vấn ngữ nghĩa, chẳng hạn như "How can I map Firestore documents with Swift" (Làm cách nào để liên kết tài liệu Firestore với Swift) (miễn là ít nhất một trong các ghi chú bạn thêm có chứa văn bản thảo luận về chủ đề này). - Bạn có thể thấy một lỗi trong trạng thái
- Nguyên nhân là do thiếu chỉ mục. Để thiết lập cấu hình chỉ mục bị thiếu, hãy truy cập vào Google Cloud Console cho dự án của bạn bằng cách truy cập vào đường liên kết này, sau đó chọn dự án của bạn trong danh sách
- Trong Cloud Log Explorer, bạn sẽ thấy thông báo lỗi "FAILED_PRECONDITION: Missing vector index configuration" (FAILED_PRECONDITION: Thiếu cấu hình chỉ mục vectơ). Vui lòng tạo chỉ mục bắt buộc bằng lệnh gcloud sau: ..."
- Thông báo lỗi cũng chứa lệnh
gcloud
mà bạn cần chạy để định cấu hình chỉ mục bị thiếu. - Chạy lệnh sau từ dòng lệnh. Nếu bạn chưa cài đặt CLI
gcloud
trên máy, hãy làm theo hướng dẫn tại đây để cài đặt CLI. Quá trình tạo chỉ mục sẽ mất vài phút. Bạn có thể kiểm tra tiến trình trên thẻ Chỉ mục trong mục Firestore của bảng điều khiển Firebase.gcloud alpha firestore indexes composite create --project=INSERT-YOUR=PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
- Sau khi chỉ mục được thiết lập, bạn có thể tạo tài liệu truy vấn mới.
- Bây giờ, bạn sẽ thấy danh sách các mã tài liệu trùng khớp trong trường kết quả
- Sao chép một trong các mã nhận dạng đó rồi quay lại bộ sưu tập
notes
. - Nhấn tổ hợp phím ⌘+F để tìm mã tài liệu mà bạn đã sao chép – tài liệu này là tài liệu phù hợp nhất với truy vấn của bạn.
7. Triển khai tính năng tìm kiếm ngữ nghĩa
Cuối cùng, đã đến lúc kết nối ứng dụng di động của bạn với tính năng Tìm kiếm vectơ bằng tiện ích Firestore và triển khai tính năng tìm kiếm ngữ nghĩa để cho phép người dùng tìm kiếm ghi chú bằng các truy vấn bằng ngôn ngữ tự nhiên.
Kết nối hàm có thể gọi để thực hiện truy vấn
Tiện ích Tìm kiếm vectơ bằng Firestore bao gồm một Hàm trên đám mây mà bạn có thể gọi từ ứng dụng di động để truy vấn chỉ mục mà bạn đã tạo trước đó trong lớp học lập trình này. Ở bước này, bạn sẽ thiết lập kết nối giữa ứng dụng di động và hàm có thể gọi này. SDK Swift của Firebase bao gồm các API giúp việc gọi các hàm từ xa trở nên liền mạch.
- Quay lại Xcode và đảm bảo bạn đang ở trong dự án mà bạn đã nhân bản ở bước trước trong lớp học lập trình này.
- Mở tệp
NotesRepository.swift
. - Tìm dòng chứa
private lazy var vectorSearchQueryCallable: Callable
= functions.httpsCallable("")
Để gọi một Hàm trên đám mây có thể gọi, bạn cần cung cấp tên của hàm mà bạn muốn gọi.
- Chuyển đến bảng điều khiển Firebase cho dự án của bạn rồi mở mục trình đơn Hàm trong phần Bản dựng.
- Bạn sẽ thấy danh sách các hàm đã được tiện ích cài đặt.
- Tìm tệp có tên
ext-firestore-vector-search-queryCallable
rồi sao chép tên tệp đó. - Dán tên vào mã của bạn. Bây giờ, nội dung sẽ là
private lazy var vectorSearchQueryCallable: Callable<String, String> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
Gọi hàm truy vấn
- Tìm phương thức
performQuery
- Gọi hàm có thể gọi bằng cách gọi
let result = try await vectorSearchQueryCallable(searchTerm)
Vì đây là lệnh gọi từ xa nên có thể không thực hiện được.
- Thêm một số tính năng xử lý lỗi cơ bản để phát hiện mọi lỗi và ghi lại vào bảng điều khiển của Xcode.
private func performQuery(searchTerm: String) async -> [String] { do { let result = try await vectorSearchQueryCallable(searchTerm) return [result] } catch { print(error.localizedDescription) return [] } }
Kết nối giao diện người dùng
Để cho phép người dùng tìm kiếm ghi chú, bạn sẽ triển khai một thanh tìm kiếm trong màn hình danh sách ghi chú. Khi người dùng nhập một cụm từ tìm kiếm, bạn cần gọi phương thức performQuery
mà bạn đã triển khai ở bước trước. Nhờ các đối tượng sửa đổi khung hiển thị searchable
và task
do SwiftUI cung cấp, bạn chỉ cần một vài dòng mã.
- Trước tiên, hãy mở
NotesListScreen.swift
- Để thêm hộp tìm kiếm vào chế độ xem danh sách, hãy thêm đối tượng sửa đổi chế độ xem
.searchable(text: $searchTerm, prompt: "Search")
ngay phía trên dòng.navigationTitle("Notes")
- Sau đó, gọi chức năng tìm kiếm bằng cách thêm mã sau ngay bên dưới:
.task(id: searchTerm, debounce: .milliseconds(800)) {
await notesRepository.semanticSearch(searchTerm: searchTerm)
}
Đoạn mã này gọi phương thức semanticSearch
một cách không đồng bộ. Bằng cách cung cấp thời gian chờ 800 mili giây, bạn hướng dẫn công cụ sửa đổi tác vụ bật lại đầu vào của người dùng trong 0,8 giây. Điều này có nghĩa là semanticSearch
sẽ chỉ được gọi sau khi người dùng tạm dừng nhập trong hơn 0,8 giây.
Mã của bạn bây giờ sẽ có dạng như sau:
...
List(repository.notes) { note in
NavigationLink(value: note) {
NoteRowView(note: note)
}
.swipeActions {
Button(role: .destructive, action: { deleteNote(note: note) }) {
Label("Delete", systemImage: "trash")
}
}
}
.searchable(text: $searchTerm, prompt: "Search")
.task(id: searchTerm, debounce: .milliseconds(800)) {
await notesRepository.semanticSearch(searchTerm: searchTerm)
}
.navigationTitle("Notes")
...
Chạy ứng dụng
- Nhấn ⌘ + R (hoặc nhấp vào nút Chạy) để khởi chạy ứng dụng trên Trình mô phỏng iOS
- Trong lớp học lập trình này, bạn sẽ thấy các ghi chú mà bạn đã thêm vào ứng dụng trước đó, cũng như mọi ghi chú mà bạn thêm vào thông qua bảng điều khiển của Firebase
- Bạn sẽ thấy một trường tìm kiếm ở đầu danh sách Ghi chú
- Nhập một cụm từ xuất hiện trên một trong các tài liệu bạn đã thêm. Xin nhắc lại, cách này hoạt động hiệu quả nhất đối với các truy vấn ngữ nghĩa, chẳng hạn như "Cách gọi các API không đồng bộ của Firebase từ Swift" (cung cấp ít nhất một ghi chú mà bạn đã thêm có chứa văn bản thảo luận về chủ đề này).
- Bạn có thể muốn thấy kết quả tìm kiếm, nhưng thay vào đó, chế độ xem danh sách bị trống và bảng điều khiển Xcode hiển thị thông báo lỗi: "Hàm được gọi bằng đối số không hợp lệ"
Điều này có nghĩa là bạn đã gửi dữ liệu ở định dạng không chính xác.
Phân tích thông báo lỗi
- Để tìm hiểu vấn đề, hãy truy cập vào bảng điều khiển của Firebase
- Chuyển đến phần Hàm
- Tìm hàm
ext-firestore-vector-search-queryCallable
, mở trình đơn mục bổ sung bằng cách nhấp vào biểu tượng ba dấu chấm dọc - Chọn Xem nhật ký để chuyển đến trình khám phá nhật ký
- Bạn sẽ thấy thông báo lỗi
Unhandled error ZodError: [
{
"code": "invalid_type",
"expected": "object",
"received": "string",
"path": [],
"message": "Expected object, received string"
}
]
Điều này có nghĩa là bạn đã gửi dữ liệu ở định dạng không chính xác.
Sử dụng đúng loại dữ liệu
Để tìm hiểu định dạng mà tiện ích dự kiến các tham số sẽ có, hãy xem tài liệu của tiện ích.
- Chuyển đến phần Tiện ích trên bảng điều khiển của Firebase
- Nhấp vào Quản lý ->
- Trong phần Cách hoạt động của tiện ích này, bạn sẽ thấy thông số kỹ thuật của các tham số đầu vào và đầu ra.
- Quay lại Xcode và chuyển đến
NotesRepository.swift
- Thêm mã sau vào đầu tệp:
private struct QueryRequest: Codable { var query: String var limit: Int? var prefilters: [QueryFilter]? } private struct QueryFilter: Codable { var field: String var `operator`: String var value: String } private struct QueryResponse: Codable { var ids: [String] }
QueryRequest
khớp với cấu trúc của tham số đầu vào mà tiện ích dự kiến, theo tài liệu của tiện ích. Tệp này cũng chứa một thuộc tínhprefilter
lồng nhau mà bạn sẽ cần sau này.QueryResponse
khớp với cấu trúc của phản hồi của tiện ích. - Tìm thông số kỹ thuật của hàm có thể gọi và cập nhật các loại đầu vào và đầu ra
private lazy var vectorSearchQueryCallable: Callable<QueryRequest, QueryResponse> = functions.httpsCallable("ext-firestore-vector-search-queryCallable")
- Cập nhật lệnh gọi hàm có thể gọi trong
performQuery
private func performQuery(searchTerm: String) async -> [String] { do { let queryRequest = QueryRequest(query: searchTerm, limit: 2) let result = try await vectorSearchQueryCallable(queryRequest) print(result.ids) return result.ids } catch { print(error.localizedDescription) return [] } }
Chạy lại ứng dụng
- Chạy lại ứng dụng
- Nhập cụm từ tìm kiếm có chứa các cụm từ có trong một trong các ghi chú của bạn
- Giờ đây, bạn sẽ thấy danh sách ghi chú đã lọc
Lọc trước dữ liệu người dùng
Trước khi bạn nhảy múa ăn mừng, có một vấn đề với phiên bản hiện tại của ứng dụng: tập hợp kết quả chứa dữ liệu của tất cả người dùng.
Bạn có thể xác minh điều này bằng cách chạy ứng dụng trên một trình mô phỏng khác và thêm các tài liệu khác. Các tài liệu mới sẽ chỉ xuất hiện trong trình mô phỏng đó, nếu chạy lại ứng dụng trên trình mô phỏng khác, bạn sẽ chỉ thấy các tài liệu đã tạo lần đầu tiên.
Nếu thực hiện tìm kiếm, bạn sẽ nhận thấy lệnh gọi đến vectorSearchQueryCallable
trả về mã nhận dạng tài liệu có thể thuộc về người dùng khác. Để ngăn chặn điều này, chúng ta cần sử dụng bộ lọc trước.
Trong performQuery
, hãy cập nhật mã như sau:
let prefilters: [QueryFilter] = if let uid = user?.uid {
[QueryFilter(field: "userId", operator: "==", value: uid)]
}
else {
[]
}
let queryRequest = QueryRequest(query: searchTerm,
limit: 2,
prefilters: prefilters)
Thao tác này sẽ lọc trước dữ liệu dựa trên mã nhận dạng của người dùng đã đăng nhập. Như bạn có thể dự kiến, thao tác này yêu cầu bạn phải cập nhật chỉ mục Firestore.
Chạy lệnh sau đây từ dòng lệnh để xác định một chỉ mục Firestore mới bao gồm cả userId
và các vectơ nhúng trong trường embedding
.
gcloud alpha firestore indexes composite create --project=INSERT-YOUR-PROJECT-ID-HERE --collection-group=notes --query-scope=COLLECTION --field-config=order=ASCENDING,field-path=userId --field-config=vector-config='{"dimension":"768","flat": "{}"}',field-path=embedding
Sau khi hoàn tất việc tạo chỉ mục, hãy chạy lại ứng dụng để xác minh rằng ứng dụng hoạt động như mong đợi
8. Xin chúc mừng
Xin chúc mừng bạn đã hoàn thành thành công lớp học lập trình này!
Trong lớp học lập trình này, bạn đã tìm hiểu cách:
- Thiết lập cơ sở dữ liệu Cloud Firestore có bật tính năng tìm kiếm ngữ nghĩa.
- Tạo một ứng dụng SwiftUI đơn giản để tương tác với cơ sở dữ liệu.
- Triển khai thanh tìm kiếm bằng cách sử dụng đối tượng sửa đổi thành phần hiển thị có thể tìm kiếm và đối tượng sửa đổi tác vụ của SwiftUI.
- Gọi một Hàm đám mây để thực hiện tìm kiếm ngữ nghĩa trên cơ sở dữ liệu bằng cách sử dụng giao diện Có thể gọi của SDK Firestore.
Với kiến thức đã học được trong lớp học lập trình này, giờ đây, bạn có thể xây dựng các ứng dụng mạnh mẽ tận dụng tính năng tìm kiếm ngữ nghĩa của Cloud Firestore để mang đến cho người dùng trải nghiệm tìm kiếm trực quan và hiệu quả hơn.
Để tìm hiểu thêm về trường vectơ mới của Firestore và cách tính toán các vectơ nhúng, hãy xem tài liệu.