Difference Between read(), search_read(), and search() 
✅ Purpose of Each
Method
Purpose
read() Reads specified fields from known record IDs.
search() Finds records using domain filters; returns full recordset.
search_read() Combines search() + read(); returns a list of dictionaries (raw data).

 📌 Realistic Odoo Examples

1. read() – Read fields from known IDs

partners = self.env[‘res.partner’].browse([1, 2, 3])

data = partners.read([‘name’, ’email’])

🔹 Returns:

[{‘id’: 1, ‘name’: ‘ABC Corp’, ’email’: ‘abc@example.com’}, …]

  • Does not perform a search.
  • Ideal when you already have IDs (e.g., from foreign keys or other logic).
  • Lightweight and efficient for just fetching specific fields.  
2. search() – Search with domain, returns full recordset

partners = self.env[‘res.partner’].search([(‘customer_rank’, ‘>’, 0)], limit=10)

for partner in partners:

    print(partner.name, partner.email)

  • Returns recordset, not dictionary.
  • Triggers all ORM features: computed fields, related fields, prefetching.
  • Suitable when you need full object access or will use advanced logic.

3. search_read() – Optimized for raw data read

data = self.env[‘res.partner’].search_read(

    [(‘customer_rank’, ‘>’, 0)],

    fields=[‘name’, ’email’],

    limit=10

)

🔹 Returns:

[{‘id’: 1, ‘name’: ‘ABC Corp’, ’email’: ‘abc@example.com’}, …]

  • Very efficient for frontend calls, reports, or lightweight API responses.
  • Returns dictionary (not a recordset) → you cannot call .method() on result.

⚙️ Comparison Summary

Feature
read()
search()
search_read()
Input Type List of IDs Domain Domain
Output Type List of dicts Recordset List of dicts
Fetches Specific Fields ✅ Yes (fields param) ✅ (all by default, can be lazy) ✅ Yes (fields param)
Lightweight ✅ Yes ❌ Heavier (full records) ✅ Yes
Use When IDs are known You need recordset/methods You need raw data efficiently
API/Frontend Use 🚫 Not ideal 🚫 Not ideal ✅ Preferred

🧠 Final Tips

  • Use search_read() for read-only API responses or UI lists.
  • Use search() if you need to operate on records (e.g., call methods).
  • Use read() when you already have record IDs and need selected fields.