Truy vấn nâng cao — lọc, chọn trường và phân trang API

Premium

Truy vấn nâng cao: API của Omniscol cung cấp ba hướng tìm kiếm — tìm kiếm toàn văn trên toàn tài khoản, phân giải thực thể phục vụ AI, và một bộ điều phối truy vấn với bộ lọc kiểu Mango / MongoDB (where, chọn trường, sắp xếp, phân trang) áp dụng lên bất kỳ điểm truy cập đọc dữ liệu nào. Có trên những tài khoản có tích hợp API.

Ngoà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 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, asc hoặc desc. Trường giả _count.<trường> sắp xếp theo độ dài của một trường dạng mảng.
  • limitoffset — 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 viGET /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 minhGET /api/schedules/availability/{datesrange} kèm một filter, 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, endtime (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/query giữ 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.

Xem thêm