Skip to content

Mongo operators#907

Merged
abnegate merged 4 commits into
mainfrom
mongo-operators
Jun 30, 2026
Merged

Mongo operators#907
abnegate merged 4 commits into
mainfrom
mongo-operators

Conversation

@fogelito

@fogelito fogelito commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added operator-aware update and upsert support using aggregation pipelines, including complex update expressions.
    • Enhanced operator handling during upserts so inserts and updates can be applied consistently in one request.
  • Bug Fixes

    • Preserved special update expressions by preventing them from being coerced into regular stored values.
    • Improved update behavior for nested array conditions when operator-based pipeline updates are used.
  • Compatibility/Support

    • Enabled operator usage for the MongoDB adapter.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: feb48914-aed5-46a9-984a-702577d57b8e

📥 Commits

Reviewing files that changed from the base of the PR and between acf2a8f and a669499.

📒 Files selected for processing (1)
  • src/Database/Adapter/Mongo.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Database/Adapter/Mongo.php

📝 Walkthrough

Walkthrough

The MongoDB adapter adds aggregation pipeline support for operator-based updates and upserts. Casting skips Operator values, update and upsert paths branch to pipeline execution when needed, and operator support is now reported as enabled.

Changes

MongoDB Operator Pipeline Support

Layer / File(s) Summary
Operator casting guards and capability flag
src/Database/Adapter/Mongo.php
Imports Operator, adds early-return guards in castingBefore() and castingAfter() for Operator values, and changes getSupportForOperators() to true.
Pipeline construction and execution helpers
src/Database/Adapter/Mongo.php
Adds private helpers for building operator-aware pipelines, translating operators into aggregation expressions, and executing raw pipeline update/upsert commands.
updateDocument and updateDocuments operator routing
src/Database/Adapter/Mongo.php
Switches both update paths between classic $set updates and pipeline updates based on whether the record contains operators.
upsertDocuments pipeline routing
src/Database/Adapter/Mongo.php
Builds pipeline-based upserts with $ifNull _id handling and routes them through executeUpsert() when operators are present.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 Hoppity hop through the pipeline stage,
Operators twirl on the MongoDB page.
$set, $ifNull, and $filter in play,
The rabbit says: “Update the smart way!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the change, but it is too vague to clearly convey the main update. Rename it to describe the key behavior change, such as adding MongoDB operator support for updates and upserts.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mongo-operators

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.

@greptile-apps

greptile-apps Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR enables MongoDB's aggregation-pipeline update path for Operator expressions, allowing atomic numeric, string, boolean, array, and date mutations to be executed directly in the database rather than at the application layer. It also flips getSupportForOperators() from false to true so the rest of the framework routes operator-bearing documents through the new Mongo path.

  • buildOperatorPipeline / getOperatorExpression / getArrayFilterCondition translate each Operator type into its equivalent MongoDB aggregation expression inside a $set pipeline stage; updateWithPipeline and executeUpsert bypass the client helper's toObject() call that would corrupt a BSON array pipeline.
  • Casting guards (Operator::isOperator($value) early-returns) are added to both schema-cast methods so Operator PHP objects survive intact until serialisation.
  • The !empty($attribute) branch in upsertDocuments (the "increment on duplicate key" path) is not updated to handle operator-containing records; Operator objects that survive casting will be placed into a plain $set payload, which the BSON encoder cannot serialise.

Confidence Score: 3/5

Safe to merge only after addressing the $inc-path gap in upsertDocuments; that code path will throw a BSON serialization error whenever Operators and a non-empty $attribute appear in the same batch.

The upsertDocuments !empty($attribute) branch puts $record — which now contains unresolved PHP Operator objects because casting is skipped for them — directly into a '$set' update document. The BSON encoder cannot serialize those objects. The rest of the pipeline machinery (buildOperatorPipeline, updateWithPipeline, executeUpsert, getOperatorExpression) is careful and well-structured, and the standard updateDocument / updateDocuments paths look correct.

The !empty($attribute) branch of upsertDocuments in src/Database/Adapter/Mongo.php (lines 2073–2092) needs a buildOperatorPipeline guard identical to the one added in the else branch.

Important Files Changed

Filename Overview
src/Database/Adapter/Mongo.php Adds aggregation-pipeline update support for Operators; the $inc-path branch in upsertDocuments does not guard against Operator instances surviving into its plain $set payload, causing a BSON serialization error at runtime when that path is combined with operator-containing documents.

Comments Outside Diff (1)

  1. src/Database/Adapter/Mongo.php, line 2073-2092 (link)

    P1 Operator instances leak into plain $set when $attribute is non-empty

    The !empty($attribute) branch puts $record directly into '$set' => $record without calling buildOperatorPipeline. Because casting is now bypassed for operators (Operator::isOperator($value) returns early in both casting methods), any Operator PHP object in the document survives into this $set payload. The BSON encoder cannot serialize PHP Operator objects and will throw a runtime error when a caller combines a non-empty $attribute argument with Operator-containing documents in the same upsertDocuments batch. The fix follows the same pattern used in the else branch: call buildOperatorPipeline($record) and, if it returns a pipeline, build a pipeline-based update instead of a plain $set.

Reviews (4): Last reviewed commit: "Merge branch 'main' into mongo-operators" | Re-trigger Greptile

Comment thread src/Database/Adapter/Mongo.php

@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 `@src/Database/Adapter/Mongo.php`:
- Around line 1447-1450: Operator values in Mongo::buildOperatorPipeline() are
currently skipped entirely, which leaves literal operands uncast and can pass
raw strings into $literal for typed attributes. Update the operator-handling
path in Mongo so the field expression stays untouched, but the operands used by
buildOperatorPipeline() are cast to the target attribute type before the
pipeline is assembled; also make sure the same casting behavior is applied in
the other operator-related blocks referenced by the review so datetime arrays
and similar typed operands are encoded as Mongo UTCDateTime values instead of
strings.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10051415-6227-4a2b-ade4-7162b0d73df4

📥 Commits

Reviewing files that changed from the base of the PR and between 0dfae8c and acf2a8f.

📒 Files selected for processing (1)
  • src/Database/Adapter/Mongo.php

Comment thread src/Database/Adapter/Mongo.php
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Comment thread src/Database/Adapter/Mongo.php Outdated
@abnegate abnegate merged commit 6d5a86b into main Jun 30, 2026
22 checks passed
@abnegate abnegate deleted the mongo-operators branch June 30, 2026 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants