Skip to content

Add support for Dynamic Search Rules#1238

Open
w1ndcn wants to merge 5 commits into
meilisearch:mainfrom
w1ndcn:feat/dynamic-search-rules
Open

Add support for Dynamic Search Rules#1238
w1ndcn wants to merge 5 commits into
meilisearch:mainfrom
w1ndcn:feat/dynamic-search-rules

Conversation

@w1ndcn

@w1ndcn w1ndcn commented Jun 5, 2026

Copy link
Copy Markdown

Add support for Dynamic Search Rules

Summary

Add support for Meilisearch v1.41's Dynamic Search Rules feature. This introduces four new methods on the Client class for managing dynamic search rules, along with the corresponding models, tests, and code samples.

Changes

New files

  • meilisearch/models/dynamic_search_rule.py — Pydantic models for DynamicSearchRule and DynamicSearchRuleResults
  • tests/client/test_client_dynamic_search_rules_meilisearch.py — 7 test cases covering CRUD operations

Modified files

  • meilisearch/config.py — Added dynamic_search_rules = "dynamic-search-rules" path constant
  • meilisearch/client.py — Added 4 methods: get_dynamic_search_rules, get_dynamic_search_rule, create_or_update_dynamic_search_rule, delete_dynamic_search_rule
  • .code-samples.meilisearch.yaml — Added 4 code samples: list_dynamic_search_rules_1, get_dynamic_search_rule_1, patch_dynamic_search_rule_1, delete_dynamic_search_rule_1

New methods

Method HTTP Endpoint
get_dynamic_search_rules() POST /dynamic-search-rules
get_dynamic_search_rule(uid) GET /dynamic-search-rules/{uid}
create_or_update_dynamic_search_rule(uid, options) PATCH /dynamic-search-rules/{uid}
delete_dynamic_search_rule(uid) DELETE /dynamic-search-rules/{uid}

Related issue

Closes #1227

Summary

This PR adds Meilisearch v1.41 Dynamic Search Rules support to the Python SDK, allowing SDK users to pin documents at the top of search results via four new Client methods. It introduces dedicated Pydantic models, adds comprehensive CRUD test coverage (including list pagination/filters), enables the feature in tests via an experimental-features fixture, and updates documentation code samples.

Changes

New Methods in Client

  • get_dynamic_search_rules(parameters: Optional[Mapping[str, Any]] = None) → List rules via POST /dynamic-search-rules, sending an empty body when no parameters are provided; supports offset, limit, and filter in the request body.
  • get_dynamic_search_rule(uid) → Retrieve a rule via GET /dynamic-search-rules/{uid}
  • create_or_update_dynamic_search_rule(uid, options) → Create/update via PATCH /dynamic-search-rules/{uid}
  • delete_dynamic_search_rule(uid) → Delete via DELETE /dynamic-search-rules/{uid} and return the HTTP status code

New Models

Added meilisearch/models/dynamic_search_rule.py:

  • DynamicSearchRule (uid plus optional description, priority, active, conditions, and actions)
  • DynamicSearchRuleResults (results plus pagination fields: offset, limit, total)

Test Coverage

Updated tests/client/test_client_dynamic_search_rules_meilisearch.py with 7 tests covering:

  • listing rules when empty
  • listing rules with offset/limit/filter (including active filtering)
  • create/update (PATCH) with structured conditions/actions
  • get by UID (and not-found behavior)
  • update existing rule (same uid)
  • delete rule (including 204 and subsequent not-found behavior)
  • delete non-existent rule error handling
    Also includes explicit assertions to reduce flaky pagination behavior.

Test Configuration

  • Added enable_dynamic_search_rules fixture in tests/conftest.py to toggle experimental-features.dynamicSearchRules on/off around the tests.

Configuration

  • Added Config.Paths.dynamic_search_rules = "dynamic-search-rules" in meilisearch/config.py.

Documentation / Code Samples

Updated .code-samples.meilisearch.yaml with:

  • list_dynamic_search_rules_1
  • get_dynamic_search_rule_1
  • patch_dynamic_search_rule_1
  • delete_dynamic_search_rule_1

Related

Closes #1227

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3762f717-5170-4e87-8326-916ceabcaec1

📥 Commits

Reviewing files that changed from the base of the PR and between dd1a55a and 9e7a7af.

📒 Files selected for processing (1)
  • tests/client/test_client_dynamic_search_rules_meilisearch.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/client/test_client_dynamic_search_rules_meilisearch.py

📝 Walkthrough

Walkthrough

Adds Meilisearch Dynamic Search Rules support: new models and config path, four Client CRUD methods (list, get, create-or-update, delete), tests exercising all flows with a fixture toggling the feature, and documentation code samples.

Changes

Dynamic Search Rules API Support

Layer / File(s) Summary
Data Models and Configuration
meilisearch/models/dynamic_search_rule.py, meilisearch/config.py
DynamicSearchRule and DynamicSearchRuleResults models define rule metadata and paginated responses; Config.Paths.dynamic_search_rules maps the endpoint path.
Client API Methods
meilisearch/client.py
Four new Client methods implement listing (POST), retrieving (GET), creating/updating (PATCH), and deleting (DELETE) Dynamic Search Rules and return typed models or status codes.
Tests and Fixture
tests/client/test_client_dynamic_search_rules_meilisearch.py, tests/conftest.py
Eight tests cover empty list, paginated list with filters, create/update, update, fetch, not-found errors, delete (returning 204), and delete-not-found; enable_dynamic_search_rules fixture toggles the experimental feature around tests.
Documentation Code Samples
.code-samples.meilisearch.yaml
Adds four YAML snippets: list_dynamic_search_rules_1, get_dynamic_search_rule_1, patch_dynamic_search_rule_1, and delete_dynamic_search_rule_1.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

"I hopped through code with a curious sniff,
Models and methods all lined up swift,
Tests cheered loud while fixtures danced true,
Docs show the steps — now rules can hop through! 🐇"

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add support for Dynamic Search Rules' accurately and specifically describes the main objective of the changeset, clearly summarizing the primary feature addition.
Linked Issues check ✅ Passed The pull request fulfills all requirements from issue #1227: implements four new Client methods (list, get, create-or-update, delete), provides comprehensive test coverage, and adds code samples matching required keys.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing Dynamic Search Rules support as specified in issue #1227; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/client/test_client_dynamic_search_rules_meilisearch.py`:
- Around line 8-14: test_get_dynamic_search_rules_empty can be flaky because
dynamic rules created by other tests are not cleaned up; before asserting empty,
call client.get_dynamic_search_rules() and delete any existing rules to make the
test deterministic (e.g., iterate over the results from
client.get_dynamic_search_rules() and call the client delete method for each
rule such as client.delete_dynamic_search_rule(rule["name"]) or the appropriate
delete API on your client) then re-query with client.get_dynamic_search_rules()
and assert results is an empty list.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e80c737b-b318-4793-bd03-f9e75d18b8d0

📥 Commits

Reviewing files that changed from the base of the PR and between ada25db and 68831d5.

📒 Files selected for processing (5)
  • .code-samples.meilisearch.yaml
  • meilisearch/client.py
  • meilisearch/config.py
  • meilisearch/models/dynamic_search_rule.py
  • tests/client/test_client_dynamic_search_rules_meilisearch.py

Comment thread tests/client/test_client_dynamic_search_rules_meilisearch.py
@Strift Strift added the enhancement New feature or request label Jun 8, 2026

@Strift Strift left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @w1ndcn and thank you for your contribution!

CI is not passing. Please make sure tests, linters, and formatters pass locally before asking another review :)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/conftest.py`:
- Around line 359-370: The PATCH calls in the enable_dynamic_search_rules
fixture currently ignore responses; update both requests.patch invocations (the
one before yield and the one after yield) to capture their return values (e.g.,
resp = requests.patch(...)) and call resp.raise_for_status() immediately after
each call so any HTTP errors surface and prevent leaving the server in the wrong
state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f57de259-5131-46d4-8f7f-8094dfd3606d

📥 Commits

Reviewing files that changed from the base of the PR and between 68831d5 and 7e2fd46.

📒 Files selected for processing (4)
  • meilisearch/client.py
  • meilisearch/models/dynamic_search_rule.py
  • tests/client/test_client_dynamic_search_rules_meilisearch.py
  • tests/conftest.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • meilisearch/models/dynamic_search_rule.py
  • meilisearch/client.py
  • tests/client/test_client_dynamic_search_rules_meilisearch.py

Comment thread tests/conftest.py
@w1ndcn

w1ndcn commented Jun 8, 2026

Copy link
Copy Markdown
Author

@Strift I've fixed the CI failures:

  1. Ran isort + black to fix formatting issues
  2. Added the enable_dynamic_search_rules fixture in conftest.py to enable the experimental feature before tests
    CI should pass now. Could you re-run it? Thanks!

@w1ndcn w1ndcn requested a review from Strift June 8, 2026 12:03
@w1ndcn

w1ndcn commented Jun 14, 2026

Copy link
Copy Markdown
Author

@Strift Hi, when you have time, could you please take another look at this PR? Thanks!

@Strift Strift left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!

Please note the API for get_dynamic_search_rules() should accept offset, limit, and filter in the POST body; see docs.

Can you add this extra param? You can take example from the other list methods in the SDK, e.g., get_keys(parameters=None), get_indexes(parameters=None), get_tasks(parameters=None).

Accept offset, limit, and filter in the POST body, matching the
pattern used by get_keys, get_indexes, and get_tasks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
tests/client/test_client_dynamic_search_rules_meilisearch.py (1)

36-37: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add count verification to the active filter test.

The filter test correctly asserts that all returned rules have active=True, but it doesn't verify that exactly 2 active rules are returned (the count created by this test). If other tests leave active rules behind, the assertion passes without confirming the filter worked as intended.

🔍 Suggested enhancement
 # Test with filter on active status
 rules = client.get_dynamic_search_rules({"filter": {"active": True}})
+assert len(rules.results) == 2, "Expected 2 active rules from this test"
 assert all(r.active is True for r in rules.results)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/client/test_client_dynamic_search_rules_meilisearch.py` around lines 36
- 37, The test for the active filter in the get_dynamic_search_rules call
verifies that all returned rules have active=True, but fails to verify the count
of returned rules. Add an assertion after the existing assertion to confirm that
exactly 2 active rules are returned (since the test creates 2 active rules),
preventing false positives if other tests leak active rules into the system.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/client/test_client_dynamic_search_rules_meilisearch.py`:
- Around line 32-33: The assertion that len(rules.results) == 2 after calling
client.get_dynamic_search_rules() with offset=1 assumes exactly 3 rules exist in
total, which is not guaranteed by test isolation. Before the offset assertion,
first verify the total count by calling client.get_dynamic_search_rules()
without offset and asserting that it returns exactly 3 results, ensuring the
pagination test makes deterministic assertions only when the required
precondition is met. This guards against prior tests that may have created rules
without proper cleanup.

---

Duplicate comments:
In `@tests/client/test_client_dynamic_search_rules_meilisearch.py`:
- Around line 36-37: The test for the active filter in the
get_dynamic_search_rules call verifies that all returned rules have active=True,
but fails to verify the count of returned rules. Add an assertion after the
existing assertion to confirm that exactly 2 active rules are returned (since
the test creates 2 active rules), preventing false positives if other tests leak
active rules into the system.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1c55d783-1ed5-44cc-beb6-f59f06da7de8

📥 Commits

Reviewing files that changed from the base of the PR and between 7e2fd46 and 67639b6.

📒 Files selected for processing (2)
  • meilisearch/client.py
  • tests/client/test_client_dynamic_search_rules_meilisearch.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • meilisearch/client.py

Comment thread tests/client/test_client_dynamic_search_rules_meilisearch.py
Prevents flaky test failure by checking the precondition (3 rules exist)
before asserting offset behavior.
@w1ndcn

w1ndcn commented Jun 16, 2026

Copy link
Copy Markdown
Author

@Strift Thanks for the suggestion! This has been addressed in the latest commit.

get_dynamic_search_rules() now accepts an optional parameters argument (Optional[Mapping[str, Any]] = None) that passes offset, limit, and filter in the POST body. The pattern follows the existing list methods like get_keys(parameters=None), get_indexes(parameters=None), and get_tasks(parameters=None), with the key difference being that those use GET + query strings while this one uses POST + request body.

A test for the new parameter support has also been added.

@w1ndcn w1ndcn requested a review from Strift June 16, 2026 06:26
@Strift

Strift commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Tests are failing again

@w1ndcn

w1ndcn commented Jun 16, 2026

Copy link
Copy Markdown
Author

@Strift The CI failure was caused by test_get_dynamic_search_rules_with_parameters creating dynamic search rules without the actions field. Meilisearch requires actions to be a non-empty list. I've added conditions and actions to all test cases that create rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Meilisearch v1.41] Add support for Dynamic Search Rules

2 participants