docs: add comprehensive join feature documentation#3551
docs: add comprehensive join feature documentation#3551
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
📝 WalkthroughWalkthroughThis pull request introduces comprehensive documentation and code samples for a new "Joins" feature in Meilisearch, enabling relationships between documents across indices. Documentation covers foreign key definitions, filtering joined data, precise array filtering, RBAC implementations, and best practices with corresponding code samples. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
capabilities/indexing/joins/overview.mdx (1)
45-45: Use "for example" instead of "e.g." per coding guidelines.Suggested fix
-- You want to **filter by related data** (e.g., find all deals where the company is in the Technology industry) +- You want to **filter by related data** (for example, find all deals where the company is in the Technology industry)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/indexing/joins/overview.mdx` at line 45, The sentence containing "You want to **filter by related data** (e.g., find all deals where the company is in the Technology industry)" should use "for example" instead of the abbreviation "e.g."; update that exact phrase to read "... (for example, find all deals where the company is in the Technology industry)" so it conforms to the coding guidelines.capabilities/indexing/advanced/optimization.mdx (1)
9-9: Use "for example" instead of "e.g." per coding guidelines.The guidelines prefer spelling out "for example" over abbreviations to keep the text accessible.
Suggested fix
-When you have relational data (e.g., deals, companies, and users), storing full related objects in every document increases index size significantly. Instead, store only the IDs of related documents and use joins to hydrate them at search time. +When you have relational data (for example, deals, companies, and users), storing full related objects in every document increases index size significantly. Instead, store only the IDs of related documents and use joins to hydrate them at search time.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/indexing/advanced/optimization.mdx` at line 9, The sentence currently uses the abbreviation "e.g." — update the phrase in the sentence that starts "When you have relational data (e.g., deals, companies, and users)" to use "for example" instead (e.g., change to "When you have relational data, for example, deals, companies, and users") so it follows the guideline to spell out "for example"; ensure punctuation and spacing are adjusted accordingly and rebuild the doc if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Around line 328-330: The Card component's href currently points to
"/capabilities/filtering_sorting_faceting/getting_started/filtering" which is
incorrect; update the Card (the element with title "Filtering basics") so its
href removes the "/filtering" suffix and points to
"/capabilities/filtering_sorting_faceting/getting_started" (the actual
getting_started page).
In `@capabilities/indexing/joins/how_to/define_join_relationships.mdx`:
- Around line 220-226: Clarify the behavior of sending an empty object to the
PATCH /indexes/{uid}/settings/join-configurations endpoint: update the example
and surrounding text to explicitly state whether PATCH with '{}' removes all
join configurations for the specified index (clearing all relationships) or
resets settings to the default state of "no relationships"; mention the exact
endpoint path "PATCH /indexes/deals/settings/join-configurations" and the curl
example shown, and add a short note describing the expected resulting state
(e.g., "all join configurations removed — index will have no relationships" or
"settings reset to defaults") so readers know the outcome.
In `@capabilities/indexing/joins/how_to/hydration_during_search.mdx`:
- Around line 270-271: The sentence in hydration_during_search.mdx saying "no
documented cardinality limits for relationships" is misleading because filtering
has a hard limit of 100 matching documents; update that sentence to explicitly
state that the 100-document limit applies to foreign filters (filtering) and
does not apply to hydration, and add a short cross-reference to the
filtering_by_joined_data.mdx section (the "foreign filters / 100 matching
documents" discussion) so readers aren’t confused about which behavior is
limited. Ensure the new phrasing mentions "100 matching documents for foreign
filters" and clarifies that hydration performance should still be tested but is
not subject to the same documented limit.
- Around line 259-266: The example for the Meilisearch delete-by-filter curl
request uses array-style filter syntax but the endpoint requires the
string-based filter format; update the request body in the curl snippet that
calls "indexes/deals/delete-by-filter" so the "filter" value is a string (e.g.,
"company_id IN [deleted_company_1, deleted_company_2]") instead of an array,
preserving the rest of the curl flags and headers.
---
Nitpick comments:
In `@capabilities/indexing/advanced/optimization.mdx`:
- Line 9: The sentence currently uses the abbreviation "e.g." — update the
phrase in the sentence that starts "When you have relational data (e.g., deals,
companies, and users)" to use "for example" instead (e.g., change to "When you
have relational data, for example, deals, companies, and users") so it follows
the guideline to spell out "for example"; ensure punctuation and spacing are
adjusted accordingly and rebuild the doc if needed.
In `@capabilities/indexing/joins/overview.mdx`:
- Line 45: The sentence containing "You want to **filter by related data**
(e.g., find all deals where the company is in the Technology industry)" should
use "for example" instead of the abbreviation "e.g."; update that exact phrase
to read "... (for example, find all deals where the company is in the Technology
industry)" so it conforms to the coding guidelines.
🪄 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: d7a55a9b-ccb2-437c-9458-e81fe897d4e3
📒 Files selected for processing (7)
.gitignorecapabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdxcapabilities/indexing/advanced/optimization.mdxcapabilities/indexing/joins/how_to/define_join_relationships.mdxcapabilities/indexing/joins/how_to/hydration_during_search.mdxcapabilities/indexing/joins/overview.mdxdocs.json
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx
Outdated
Show resolved
Hide resolved
capabilities/indexing/joins/how_to/define_join_relationships.mdx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
♻️ Duplicate comments (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx (1)
328-330:⚠️ Potential issue | 🟡 MinorFix unresolved broken
Cardlink in “Filtering basics.”The
hrefstill points to/getting_started/filtering, which does not match the documented target page path and breaks navigation.Suggested fix
- <Card title="Filtering basics" href="/capabilities/filtering_sorting_faceting/getting_started/filtering"> + <Card title="Filtering basics" href="/capabilities/filtering_sorting_faceting/getting_started"> Return to basic filtering guide </Card>Based on learnings: “When adding or moving content, update or add links from related pages so users can find it”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx` around lines 328 - 330, The Card component at "Card title=\"Filtering basics\"" has a broken href pointing to "/capabilities/filtering_sorting_faceting/getting_started/filtering"; update the href on that Card in filtering_by_joined_data.mdx to the correct documented path (e.g., "/capabilities/filtering_sorting_faceting/getting_started/filtering") or the appropriate relative path so the link resolves and navigation works; ensure the href string exactly matches the target page slug used elsewhere in the docs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Around line 328-330: The Card component at "Card title=\"Filtering basics\""
has a broken href pointing to
"/capabilities/filtering_sorting_faceting/getting_started/filtering"; update the
href on that Card in filtering_by_joined_data.mdx to the correct documented path
(e.g., "/capabilities/filtering_sorting_faceting/getting_started/filtering") or
the appropriate relative path so the link resolves and navigation works; ensure
the href string exactly matches the target page slug used elsewhere in the docs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 41c7660c-3429-41a2-8ac8-31685f71dc98
📒 Files selected for processing (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx (1)
274-276:⚠️ Potential issue | 🟡 MinorFix broken link to filtering basics page.
The href points to
/capabilities/filtering_sorting_faceting/getting_started/filtering, but the actual file iscapabilities/filtering_sorting_faceting/getting_started.mdx. Remove the/filteringsuffix.🔗 Proposed fix
- <Card title="Filtering basics" href="/capabilities/filtering_sorting_faceting/getting_started/filtering"> + <Card title="Filtering basics" href="/capabilities/filtering_sorting_faceting/getting_started"> Return to basic filtering guide </Card>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx` around lines 274 - 276, Update the Card component's href so it points to the actual getting_started page: change the href value on the Card with title "Filtering basics" from "/capabilities/filtering_sorting_faceting/getting_started/filtering" to "/capabilities/filtering_sorting_faceting/getting_started" (remove the trailing "/filtering") so the link resolves to capabilities/filtering_sorting_faceting/getting_started.mdx.
🧹 Nitpick comments (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx (1)
100-100: Consider more direct phrasing.The phrase "a specific one" could be more concrete. Consider "a specific company" for clarity.
✏️ Optional rewording
-Filter deals where the company is a specific one: +Filter deals where the company is a specific company:Or more concisely:
-Filter deals where the company is a specific one: +Filter deals by a specific company:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx` at line 100, Replace the vague phrase "Filter deals where the company is a specific one:" with a clearer, more direct wording such as "Filter deals where the company is a specific company:" or even more concise "Filter deals for a specific company:" in the document (look for that exact sentence in filtering_by_joined_data.mdx) to improve clarity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Line 46: Update the heading "## How it works: Normalized vs. Denormalized" to
sentence-style capitalization by capitalizing only the first word and proper
nouns; change it to "## How it works: normalized vs. denormalized" in the file
(look for the heading text "How it works: Normalized vs. Denormalized" to find
the exact spot).
---
Duplicate comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Around line 274-276: Update the Card component's href so it points to the
actual getting_started page: change the href value on the Card with title
"Filtering basics" from
"/capabilities/filtering_sorting_faceting/getting_started/filtering" to
"/capabilities/filtering_sorting_faceting/getting_started" (remove the trailing
"/filtering") so the link resolves to
capabilities/filtering_sorting_faceting/getting_started.mdx.
---
Nitpick comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Line 100: Replace the vague phrase "Filter deals where the company is a
specific one:" with a clearer, more direct wording such as "Filter deals where
the company is a specific company:" or even more concise "Filter deals for a
specific company:" in the document (look for that exact sentence in
filtering_by_joined_data.mdx) to improve clarity.
🪄 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: 1b41fd05-e0d2-4101-8ce7-7039573b11bc
📒 Files selected for processing (4)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdxcapabilities/filtering_sorting_faceting/advanced/precise_filtering_array_items.mdxcapabilities/security/advanced/rbac_with_joins.mdxdocs.json
✅ Files skipped from review due to trivial changes (3)
- capabilities/security/advanced/rbac_with_joins.mdx
- docs.json
- capabilities/filtering_sorting_faceting/advanced/precise_filtering_array_items.mdx
| }' | ||
| ``` | ||
|
|
||
| ## How it works: Normalized vs. Denormalized |
There was a problem hiding this comment.
Fix heading capitalization to use sentence-style.
The heading capitalizes "Denormalized" but sentence-style capitalization requires only the first word and proper nouns to be capitalized. As per coding guidelines, use sentence-style capitalization in headings.
📝 Proposed fix
-## How it works: Normalized vs. Denormalized
+## How it works: Normalized vs. denormalized🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`
at line 46, Update the heading "## How it works: Normalized vs. Denormalized" to
sentence-style capitalization by capitalizing only the first word and proper
nouns; change it to "## How it works: normalized vs. denormalized" in the file
(look for the heading text "How it works: Normalized vs. Denormalized" to find
the exact spot).
- Update all curl examples to use correct /settings endpoint - Change parameters from sourceField/targetIndex/targetField to foreignKeys array - Add proper filterableAttributes configuration - Update configuration parameters table with correct fields - Fix one-to-one, one-to-many, many-to-many examples - Fix all common patterns (e-commerce, SaaS, marketplace) - Fix self-references example - Fix update and remove relationship examples
…isearch/documentation into docs/add-join-feature-documentation
…cleanup - Add facetSearch and comparison fields to all filterableAttributes examples - Remove hydration_during_search page (hydration is automatic) - Add edit-by-function cleanup strategy for orphaned references
… page Consolidate joins documentation into capabilities/indexing/joins/define_index_relationships.mdx and update all internal links.
Replace pseudocode diagram with JSON examples in joins page. Replace pseudocode server example with JavaScript in RBAC page.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx (1)
47-47:⚠️ Potential issue | 🟡 MinorFix heading to sentence-style capitalization.
At Line 47, update
## How it works: Normalized vs. Denormalizedto sentence style:## How it works: normalized vs. denormalized.As per coding guidelines, “Use sentence-style capitalization in headings (first word and proper nouns only).”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx` at line 47, The heading "## How it works: Normalized vs. Denormalized" should use sentence-style capitalization; update the heading text to "## How it works: normalized vs. denormalized" by replacing the existing heading string (## How it works: Normalized vs. Denormalized) with the corrected sentence-style version in the document (the heading line beginning with "## How it works:").
🧹 Nitpick comments (1)
capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx (1)
87-87: Shorten this sentence for clarity.At Line 87, consider:
Filter deals from a specific company:As per coding guidelines, “Prefer short, direct sentences and avoid jargon when a simpler term exists in documentation.”
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx` at line 87, Replace the sentence "Filter deals where the company is a specific one:" with the shorter, clearer phrasing "Filter deals from a specific company:" in the documentation; locate the existing sentence text "Filter deals where the company is a specific one:" (in filtering_by_joined_data content) and update it to the suggested wording to follow the guideline preferring short, direct sentences.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Line 47: The heading "## How it works: Normalized vs. Denormalized" should use
sentence-style capitalization; update the heading text to "## How it works:
normalized vs. denormalized" by replacing the existing heading string (## How it
works: Normalized vs. Denormalized) with the corrected sentence-style version in
the document (the heading line beginning with "## How it works:").
---
Nitpick comments:
In
`@capabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx`:
- Line 87: Replace the sentence "Filter deals where the company is a specific
one:" with the shorter, clearer phrasing "Filter deals from a specific company:"
in the documentation; locate the existing sentence text "Filter deals where the
company is a specific one:" (in filtering_by_joined_data content) and update it
to the suggested wording to follow the guideline preferring short, direct
sentences.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a23100d0-a835-47ff-bbac-2bb51bc7ec04
📒 Files selected for processing (35)
.code-samples.meilisearch.yaml.gitignorecapabilities/filtering_sorting_faceting/advanced/filter_expression_syntax.mdxcapabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdxcapabilities/filtering_sorting_faceting/advanced/precise_filtering_array_items.mdxcapabilities/filtering_sorting_faceting/overview.mdxcapabilities/indexing/advanced/indexing_best_practices.mdxcapabilities/indexing/joins/define_index_relationships.mdxcapabilities/security/advanced/rbac_with_joins.mdxcapabilities/security/overview.mdxdocs.jsonsnippets/generated-code-samples/code_samples_foreign_filter_array_and_logic_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_array_or_logic_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_basic_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_certifications_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_combined_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_date_range_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_equality_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_multiple_conditions_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_multiple_equality_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_range_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_skills_1.mdxsnippets/generated-code-samples/code_samples_foreign_filter_tags_1.mdxsnippets/generated-code-samples/code_samples_joins_define_relationship_1.mdxsnippets/generated-code-samples/code_samples_joins_delete_orphaned_1.mdxsnippets/generated-code-samples/code_samples_joins_many_to_many_1.mdxsnippets/generated-code-samples/code_samples_joins_multiple_relationships_1.mdxsnippets/generated-code-samples/code_samples_joins_one_to_many_1.mdxsnippets/generated-code-samples/code_samples_joins_one_to_one_1.mdxsnippets/generated-code-samples/code_samples_joins_remove_orphaned_ids_1.mdxsnippets/generated-code-samples/code_samples_joins_remove_relationships_1.mdxsnippets/generated-code-samples/code_samples_joins_self_reference_1.mdxsnippets/generated-code-samples/code_samples_joins_update_relationship_1.mdxsnippets/generated-code-samples/code_samples_rbac_multi_level_1.mdxsnippets/generated-code-samples/code_samples_rbac_search_with_foreign_filter_1.mdx
✅ Files skipped from review due to trivial changes (32)
- .gitignore
- snippets/generated-code-samples/code_samples_foreign_filter_array_or_logic_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_tags_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_array_and_logic_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_multiple_equality_1.mdx
- snippets/generated-code-samples/code_samples_joins_remove_relationships_1.mdx
- capabilities/filtering_sorting_faceting/overview.mdx
- capabilities/indexing/advanced/indexing_best_practices.mdx
- snippets/generated-code-samples/code_samples_joins_delete_orphaned_1.mdx
- snippets/generated-code-samples/code_samples_rbac_multi_level_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_date_range_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_skills_1.mdx
- snippets/generated-code-samples/code_samples_joins_update_relationship_1.mdx
- snippets/generated-code-samples/code_samples_joins_remove_orphaned_ids_1.mdx
- snippets/generated-code-samples/code_samples_joins_many_to_many_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_equality_1.mdx
- capabilities/filtering_sorting_faceting/advanced/filter_expression_syntax.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_combined_1.mdx
- snippets/generated-code-samples/code_samples_joins_one_to_one_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_range_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_certifications_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_basic_1.mdx
- snippets/generated-code-samples/code_samples_rbac_search_with_foreign_filter_1.mdx
- snippets/generated-code-samples/code_samples_joins_define_relationship_1.mdx
- snippets/generated-code-samples/code_samples_foreign_filter_multiple_conditions_1.mdx
- snippets/generated-code-samples/code_samples_joins_multiple_relationships_1.mdx
- snippets/generated-code-samples/code_samples_joins_self_reference_1.mdx
- capabilities/filtering_sorting_faceting/advanced/precise_filtering_array_items.mdx
- capabilities/security/advanced/rbac_with_joins.mdx
- snippets/generated-code-samples/code_samples_joins_one_to_many_1.mdx
- .code-samples.meilisearch.yaml
- capabilities/indexing/joins/define_index_relationships.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
- docs.json
| The following expression returns all deals where the related company is in the Technology industry: | ||
|
|
||
| <CodeGroup> | ||
|
|
||
| ``` | ||
| _foreign(company, industry = "Technology") | ||
| ``` | ||
|
|
||
| </CodeGroup> |
There was a problem hiding this comment.
This kind of filter can retrieve a lot of companies, which can lead to an error :S
Summary
Add comprehensive documentation for Meilisearch's join feature (based on PR #6314), covering:
Changes
New documentation pages:
capabilities/indexing/joins/define_index_relationships.mdx— Complete guide to joins: why, how, relationship types, updates, data integrity, and cleanup strategiescapabilities/filtering_sorting_faceting/advanced/filtering_by_joined_data.mdx— Using foreign filters to filter by joined data with hard limitscapabilities/filtering_sorting_faceting/advanced/precise_filtering_array_items.mdx— Precise AND-logic filtering across array relationshipscapabilities/security/advanced/rbac_with_joins.mdx— Role-based access control using joins and tenant tokensUpdated pages:
capabilities/indexing/advanced/indexing_best_practices.mdx— Added section on using joins to reduce data duplication.code-samples.meilisearch.yaml— All curl examples moved to centralized code samples filedocs.json— Navigation entries for joins guidesKey Features Documented
foreignKeyswithfieldNameandforeignIndexUid, plusfilterableAttributeswithfacetSearch,equality, andcomparisonsettingsDocumentation Quality
.code-samples.meilisearch.yamlwith snippet importsSummary by CodeRabbit