Ở bài trước, nhiều điều kiện trong domain nối bằng VÀ ngầm định. Nhưng thực tế bạn thường cần "HOẶC", cần phủ định, cần lồng nhiều nhánh. Odoo diễn đạt những cái đó bằng ba toán tử tiền tố: &, |, !. Cú pháp này khiến người mới bối rối nhất — nhưng có một quy tắc đọc đơn giản, và bài này sẽ làm rõ.
Ký pháp tiền tố: toán tử đứng TRƯỚC
Điểm gây rối: trong domain Odoo, toán tử đứng trước các điều kiện nó nối (gọi là ký pháp Ba Lan / tiền tố), không phải ở giữa như A or B của Python.

Hình 1: Ba toán tử tiền tố. & (VÀ) là mặc định nên thường ẩn đi — [A, B] chính là ['&', A, B]. | (HOẶC) và ! (KHÔNG) phải viết tường minh. Quy tắc đọc: mỗi toán tử "ngốn" đúng số vế của nó ngay sau — | và & ngốn 2 vế, ! ngốn 1 vế. Một vế có thể lại là kết quả của một toán tử khác (lồng nhau).
Kiểm chứng bằng số đếm thật
Cách chắc chắn nhất để tin mình đọc đúng domain là đếm và đối chiếu phép tập hợp. Đây là output thật trên res.partner (30 bản ghi, company=6, có email=26):

Hình 2: Số đếm thật khớp toán học. ['|', company, email] = 28 — đúng bằng 6 + 26 - 4 (hợp hai tập). ['!', company] = 24 = 30 - 6 (phần bù). Lồng company AND (email OR phone) = 5. Ba nhánh OR (hai dấu |) = 8. Khi số đếm khớp phép tập, bạn biết mình viết domain đúng.
Ba mẫu phải thuộc
OR — một dấu | cho hai vế
# Đối tác là công ty HOẶC có email
['|', ('is_company', '=', True), ('email', '!=', False)]
Dấu | đứng đầu, rồi tới đúng hai điều kiện nó nối. Đây là lỗi sai phổ biến nhất: người mới hay viết [('is_company','=',True), '|', ('email',...)] — sai vị trí.
NOT — một dấu ! cho một vế
# KHÔNG phải công ty
['!', ('is_company', '=', True)]
! phủ định đúng một vế ngay sau. Muốn phủ định cả một nhóm thì đặt ! trước cả biểu thức nhóm đó.
Lồng: AND của (OR ...)
# Công ty VÀ (có email HOẶC có điện thoại)
[
('is_company', '=', True), # vế 1 (AND ngầm)
'|', # vế 2 = kết quả của phép OR dưới
('email', '!=', False),
('phone', '!=', False),
]
Đọc: AND ngầm nối vế 1 với kết quả của | (email OR phone). Odoo tự nhóm đúng vì mỗi toán tử ngốn đủ số vế.
Ba nhánh OR trở lên
Mỗi | chỉ nối hai vế. Muốn OR ba điều kiện, cần hai dấu |:
# A HOẶC B HOẶC C
['|', '|', A, B, C]
# đọc: | ( | (A, B), C ) → (A OR B) OR C
Quy tắc chung: OR n điều kiện cần n-1 dấu |. Với danh sách động, người ta thường dùng hàm dựng domain thay vì gõ tay (ví dụ expression.OR([...]) của Odoo).
Mẹo giữ tỉnh táo
- Nghĩ theo cây: mỗi toán tử là một nút có 1 (cho
!) hoặc 2 (cho&,|) nhánh con; điều kiện(field,op,val)là lá. - Đếm để kiểm: chạy
search_countvà đối chiếu phép tập hợp như Hình 2 — sai domain lộ ra ngay. - Với domain phức tạp/động, dùng
odoo.osv.expression.AND([...])và.OR([...])để Odoo tự chèn toán tử — an toàn hơn gõ|tay.
Nhớ ba ý
- Domain dùng toán tử tiền tố:
&(VÀ, thường ẩn),|(HOẶC),!(KHÔNG) — đứng trước các vế;|/&ngốn 2 vế,!ngốn 1 vế. - OR n điều kiện cần n-1 dấu
|; lồng nhau đọc từ trái, mỗi toán tử ngốn đủ số vế — kiểm bằng cách đếm và đối chiếu phép tập (đo thật OR=28=6+26-4). - Với domain động/phức tạp, dùng
expression.AND/expression.ORđể tránh tự chèn|sai vị trí — lỗi phổ biến nhất của người mới.
Lọc thành thạo rồi, bước tiếp là tổng hợp dữ liệu. Phần sau khám phá read_group — gom nhóm và tính tổng/đếm/trung bình ngay ở tầng CSDL, nền tảng của mọi báo cáo và biểu đồ trong Odoo.