Truy vấn nâng cao — lọc, chọn trường và phân trang API
PremiumNgoài việc gọi từng điểm truy cập một, API của Omniscol còn cung cấp ba hướng tìm kiếm. Gộp lại, chúng bao quát việc tìm kiếm toàn văn, việc chuyển một tên gọi quen thuộc thành một mã định danh kỹ thuật, và việc chạy một truy vấn có lọc, có chọn trường và có phân trang trên bất kỳ điểm truy cập đọc dữ liệu nào — mà bạn không phải tự nối nhiều lệnh gọi lại với nhau.
Chính những thành phần này trả lời các câu hỏi mà một intranet, một công cụ đặt phòng hoặc một ETL thường đặt ra nhất — bắt đầu từ “phòng học nào hoặc giáo viên nào còn rảnh vào khung giờ này?” (xem Tìm một phòng học hoặc một giáo viên còn rảnh).
Nhìn tổng quan ba hướng tìm kiếm
| Điểm truy cập | Chức năng | Phù hợp nhất cho |
|---|---|---|
POST /api/search |
Tìm kiếm toàn văn trên toàn bộ tài khoản. Tách văn bản bạn nhập thành các từ (không phân biệt hoa thường và dấu) rồi trả về những đường dẫn JSON nơi tìm thấy từng từ. | Việc dò nhanh “thuật ngữ này xuất hiện ở đâu?”. |
POST /api/search/entity |
Tra một tên ra thực thể tương ứng. Xử lý được dấu, ký tự đại diện và so khớp gần đúng (độ tương đồng Dice), rồi trả về loại thực thể, mã định danh và ngữ cảnh. | Biến “10A1” thành lớp, hay “Nguyễn Thị Mai” thành giáo viên. |
POST /api/search/query |
Bộ điều phối truy vấn: gọi một điểm truy cập đọc dữ liệu, rồi áp dụng bộ lọc where, phép chọn trường, phép sắp xếp và phép phân trang lên kết quả. |
Những câu hỏi phức tạp, có lọc, mà nếu không thì phải gọi nhiều lần. |
Cả ba đều có mặt trong tài liệu tham chiếu API tương tác (trang /developers), ở mục Search, và đều yêu cầu xác thực — xem API Omniscol.
Bộ lọc where (kiểu Mango / MongoDB)
Cả /api/search/entity lẫn /api/search/query đều nhận một mệnh đề
where: một bộ lọc có cấu trúc với các toán tử kiểu MongoDB. Một
trường ứng với hoặc một giá trị trực tiếp (mặc nhiên là bằng), hoặc một
đối tượng gồm các toán tử; nhiều toán tử trên cùng một trường được kết
hợp bằng phép VÀ ngầm định. Tên trường chấp nhận ký hiệu dấu
chấm để với tới một ngữ cảnh cha (ví dụ sites.name).
| Toán tử | Ý nghĩa |
|---|---|
$eq / $ne |
Bằng / khác |
$gt $gte $lt $lte |
Các phép so sánh |
$in / $nin |
Giá trị nằm trong / không nằm trong một danh sách |
$exists |
Trường có tồn tại |
$regex |
Biểu thức chính quy (không phân biệt hoa thường) |
$contains |
Một chuỗi hoặc một mảng có chứa một giá trị (không phân biệt hoa thường) |
$like |
So khớp gần đúng, bỏ qua dấu và dấu câu (Dice) |
$and $or $not |
Kết hợp logic |
Vài ví dụ:
{ "capacity": { "$gte": 20, "$lte": 50 } }
{ "level": { "$in": ["10", "11", "12"] } }
{ "name": { "$regex": "^lab" } }
{ "city": { "$like": "ho chi minh" } }
{ "$or": [ { "capacity": { "$gte": 50 } }, { "specialisation": "chemistry" } ] }
Chọn trường, sắp xếp và phân trang
Trên /api/search/query, bốn công cụ nữa giữ cho phản hồi luôn gọn và
có thứ tự — điều này quan trọng với một màn hình tổng hợp, và càng quan
trọng hơn với một tác nhân AI bị tính tiền theo token:
project— danh sách các trường cần giữ lại (dùng được ký hiệu dấu chấm). Mọi thứ còn lại đều bị loại bỏ.sort— một trường,aschoặcdesc. Trường giả_count.<trường>sắp xếp theo độ dài của một trường dạng mảng.limitvàoffset— phân trang kết quả.
Phản hồi còn trả về một khối meta: có bao nhiêu phần tử trước khi lọc,
bao nhiêu phần tử qua được bộ lọc, và bao nhiêu phần tử đã được trả về.
Một ví dụ đầy đủ
Tìm những phòng học có ít nhất 30 chỗ, chỉ giữ lại tên và sức chứa, xếp từ lớn xuống nhỏ, rồi lấy 20 phòng đầu tiên:
curl -X POST "https://ten-truong-cua-ban.omniscol.com/api/search/query" \
-H "Authorization: Bearer $OMNISCOL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"call": "os_dashboard_classrooms_get",
"where": { "capacity": { "$gte": 30 } },
"project": ["name", "capacity"],
"sort": { "capacity": "desc" },
"limit": 20
}'
call là tên nội bộ của điểm truy cập đọc dữ liệu cần chạy (đúng như
hiển thị trên trang /developers), params mang các tham số riêng
của điểm truy cập đó, còn extract_path chỉ ra mảng cần lọc bên trong
kết quả khi cần — ở đây được bỏ qua nên hệ thống tự phát hiện.
Tìm một phòng học hoặc một giáo viên còn rảnh
Kiểu tích hợp phổ biến nhất — cấp dữ liệu cho một intranet, một công cụ đặt phòng hay một ETL — chính là “ai hoặc cái gì còn rảnh vào lúc đó?”. Các điểm truy cập availability trả lời thẳng câu hỏi này: theo từng thực thể, chúng chỉ trả về những khung giờ còn trống trong các ngày bạn hỏi, đã tính sẵn các tiết học, các lần vắng mặt và các khai báo thời gian rảnh bắt buộc.
Có hai cách hỏi tình trạng rảnh:
- Theo phạm vi —
GET /api/schedules/availability/{datesrange}/{entity}(kèm/{entityId}khi cần) cho một loại thực thể —teachers,classrooms,groups,resources… - Bộ lọc tường minh —
GET /api/schedules/availability/{datesrange}kèm mộtfilter, nơi bạn thu hẹp tập hợp bằng chính cú pháp$wheređã thấy ở trên.
{datesrange} viết theo dạng YYYYMMDD, và các đoạn ngăn cách bằng
dấu phẩy sẽ hỏi những ngày rời rạc — rất hợp với “hai ngày thứ Hai
nhất định”: 20261005,20261012. Mỗi khung giờ trả về đều mang day,
start, end và time (tính bằng phút): vì vậy “ít nhất 3 giờ” trở
thành phép kiểm tra time >= 180 ở phía bạn.
Một giáo viên còn rảnh trong một khung giờ cụ thể
“Những giáo viên nào còn rảnh vào thứ Hai ngày 5 tháng 10?” — chỉ một lệnh gọi theo phạm vi:
curl -G "https://ten-truong-cua-ban.omniscol.com/api/schedules/availability/20261005/teachers" \
-H "Authorization: Bearer $OMNISCOL_TOKEN" \
--data-urlencode "with_entities=true"
Các khung giờ còn trống được trả về theo nhóm, trước hết theo loại thực
thể rồi theo giáo viên — ví dụ
{ "availability": { "teachers": { "gv.mai": [ { "day": "2026-10-05", "start": "14:00", "end": "17:00", "time": 180 } ] } } } —
và công cụ của bạn giữ lại người nào phủ được khung giờ cần tìm.
Những phòng học có sức chứa nhất định, còn trống trong hai ngày thứ Hai
Hãy kết hợp bộ lọc thực thể với tình trạng rảnh trong một lệnh gọi duy
nhất, dùng một tập con hữu ích của cú pháp — chỉ $where trên sức
chứa:
curl -G "https://ten-truong-cua-ban.omniscol.com/api/schedules/availability/20261005,20261012" \
-H "Authorization: Bearer $OMNISCOL_TOKEN" \
--data-urlencode 'filter={"classrooms":[{"$where":{"capacity":{"$gte":30}}}]}' \
--data-urlencode "with_entities=true"
Omniscol trả về các khung giờ còn trống, trong cả hai ngày thứ Hai, của
từng phòng học có ít nhất 30 chỗ. Sau đó ETL của bạn giữ lại những phòng
có một khoảng 3 giờ (time >= 180) trong mỗi ngày — việc ghép
nhiều ngày lại vẫn nằm ở phía bạn, nhờ vậy quy tắc luôn tường minh và
kiểm chứng được.
Với mỗi loại thực thể, filter chấp nhận một danh sách mã định danh đơn
giản ({"classrooms":["A101","B204"]}), một ký tự đại diện
({"teachers":"*"}), một phép khớp trường đơn giản
({"teachers":[{"email":"…"}]}) hoặc $where có cấu trúc như đã trình
bày ở đây.
Chọn đúng hướng tìm kiếm
- “Từ này xuất hiện ở đâu?” →
POST /api/search. - “Tên này ứng với thực thể nào?” →
POST /api/search/entity. - “Cho tôi những phòng học trên 30 chỗ, đã sắp xếp, trang đầu tiên” →
POST /api/search/query. - “Ai hoặc cái gì còn rảnh vào khung giờ này?” →
GET /api/schedules/availability/….
Dành cho một tác nhân AI
Những hướng tìm kiếm này tồn tại phần lớn là để phục vụ các tác nhân
AI. Tìm kiếm toàn văn và phân giải thực thể biến cách diễn đạt của
người dùng (“giáo viên Trần Văn Nam”, “lớp 10A1”) thành các mã định
danh chính xác; sau đó bộ điều phối truy vấn trả lời một câu hỏi có lọc
chỉ trong một lệnh gọi và chỉ trả về đúng những trường được yêu cầu —
thay vì nhiều lệnh gọi và một phản hồi quá khổ. Khi bạn kết nối một tác
nhân qua MCP — kết nối một tác nhân AI bên ngoài, những công cụ này nằm trong số những gì
nó có thể dùng.
Kết nối vào một intranet, một ETL hay một công cụ đối tác
Chính những điểm truy cập đọc dữ liệu này là thứ mà một công cụ bên thứ ba dùng hằng ngày. Vài dạng thường gặp:
- Một lượt kéo dữ liệu về intranet hoặc màn hình tổng hợp — trang của bạn gọi các điểm truy cập đọc dữ liệu (tình trạng rảnh, điểm truy cập tiết học, các bảng số liệu tổng hợp) bằng một mã thông báo API có phạm vi hạn chế, rồi hiển thị kết quả. Không phải cài đặt gì ở phía Omniscol.
- Một ETL chạy ban đêm — một tác vụ theo lịch lấy về đúng thứ nó cần
(các tiết học trong một khoảng ngày, số giờ của giáo viên, mức sử dụng
phòng học) rồi nạp vào hệ thống thông tin của bạn.
search/querygiữ cho mỗi lượt kéo đều có lọc, có chọn trường và có phân trang, nên phản hồi luôn gọn. - Một lượt đẩy dữ liệu từ hệ thống của bạn — chiều ngược lại, để giữ
Omniscol khớp với nguồn dữ liệu chuẩn của bạn: một tác vụ ban đêm có
thể cập nhật lớp và giáo viên (
POST /api/external/classes,POST /api/external/teachers) hoặc nạp một danh mục môn học tùy chỉnh (POST /api/admin/subjects/custom) từ cơ sở dữ liệu của bạn. - Một phần mềm SIS / ERP đóng gói — với Aurion, Auriga và những hệ tương tự, trình kết nối chuyên dụng mới là công cụ phù hợp — xem Đồng bộ hóa với các hệ thống bên ngoài.
- Theo hướng sự kiện — để được thông báo khi có thay đổi thay vì hỏi vòng liên tục, hãy đăng ký một hook — xem Tùy chỉnh API.
Hãy giữ cho mỗi tích hợp luôn hạn chế phạm vi: một mã thông báo chỉ dùng được đúng những điểm truy cập thật sự cần, được thay mới định kỳ, và chỉ có quyền đọc ở mọi nơi mà tích hợp chỉ cần đọc dữ liệu. Xem API Omniscol.