Skip to content

feat: Add contains-substring filter for String fields#3392

Open
dblythy wants to merge 1 commit into
parse-community:alphafrom
dblythy:fix/2153-contains-substring-filter
Open

feat: Add contains-substring filter for String fields#3392
dblythy wants to merge 1 commit into
parse-community:alphafrom
dblythy:fix/2153-contains-substring-filter

Conversation

@dblythy

@dblythy dblythy commented Jul 5, 2026

Copy link
Copy Markdown
Member

Closes #2153

Problem

For a String column, the only substring-style filter is matches regex, which passes the input to Parse.Query#matches verbatim as a regular expression. Regex metacharacters therefore have special meaning: . matches any character, and metacharacters like ( are invalid on their own, so a plain literal search either returns the wrong rows or fails with a server error. There is no way to do a simple literal substring search.

Fix

Add a separate contains substring operator for String fields, backed by the SDK's Parse.Query#contains, which wraps the input in \Q...\E so the whole value is matched literally (the same quoting startsWith / endsWith already use). The existing matches regex operator is unchanged, so raw regex remains available.

The "rename the confusing operator" half of the issue was already handled in #2991 (the old mislabelled entry was replaced by the explicit matches regex), so this PR only adds the new safe operator. This does not touch the Array-field labels discussed in #2052.

Unit test added in src/lib/tests/queryFromFilters.test.js covering literal substring matching, metacharacter escaping, and a contrast asserting matches stays a raw regex.

The new operator

The String field condition list now offers contains substring below matches regex:

new option

Literal . (data: a(b, c.d, hello, world)

matches regex treats . as a wildcard and returns every row:

matches regex dot

contains substring matches . literally and returns only c.d:

contains dot

Literal a(b

matches regex with a(b is an invalid regular expression, so the query fails (500) and nothing is shown:

matches regex paren

contains substring with a(b matches the parenthesis literally and returns the correct row:

contains paren

Summary by CodeRabbit

  • New Features

    • Added support for a new string filter option, allowing substring matching in queries.
    • Expanded the available string constraint list to include the new option.
  • Bug Fixes

    • Query filtering now correctly applies substring matching when this new constraint is used.
    • Added test coverage to ensure substring and regex-based filters behave as expected, including literal handling of special characters.

@parse-github-assistant

Copy link
Copy Markdown

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

Tip

  • Keep pull requests small. Large PRs will be rejected. Break complex features into smaller, incremental PRs.
  • Use Test Driven Development. Write failing tests before implementing functionality. Ensure tests pass.
  • Group code into logical blocks. Add a short comment before each block to explain its purpose.
  • We offer conceptual guidance. Coding is up to you. PRs must be merge-ready for human review.
  • Our review focuses on concept, not quality. PRs with code issues will be rejected. Use an AI agent.
  • Human review time is precious. Avoid review ping-pong. Inspect and test your AI-generated code.

Note

Please respond to review comments from AI agents just like you would to comments from a human reviewer. Let the reviewer resolve their own comments, unless they have reviewed and accepted your commit, or agreed with your explanation for why the feedback was incorrect.

Caution

Pull requests must be written using an AI agent with human supervision. Pull requests written entirely by a human will likely be rejected, because of lower code quality, higher review effort and the higher risk of introducing bugs. Please note that AI review comments on this pull request alone do not satisfy this requirement. Our CI and AI review are safeguards, not development tools. If many issues are flagged, rethink your development approach. Invest more effort in planning and design rather than using review cycles to fix low-quality code.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

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: 10a2e002-e944-4f20-871e-dd74472116e9

📥 Commits

Reviewing files that changed from the base of the PR and between 9db24be and cbbb047.

📒 Files selected for processing (3)
  • src/lib/Filters.js
  • src/lib/queryFromFilters.js
  • src/lib/tests/queryFromFilters.test.js

📝 Walkthrough

Walkthrough

Adds a new contains string constraint to the filter constraint catalog and allowed constraints list, adds a corresponding handler in addConstraintFromValues that calls query.contains, and adds tests validating substring escaping and existing matches regex behavior.

Changes

Contains Substring Constraint

Layer / File(s) Summary
Constraint definition and field list
src/lib/Filters.js
Adds a contains entry to the Constraints catalog (substring check, composable, comparable) and includes 'contains' in the FieldConstraints.String allowed list.
Query builder wiring and tests
src/lib/queryFromFilters.js, src/lib/tests/queryFromFilters.test.js
Adds a case 'contains' in addConstraintFromValues that calls query.contains(field, String(compareTo)), and adds a new test module verifying escaped $regex for contains and raw regex/$options behavior for matches.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User as Dashboard User
  participant Filter as Filters UI
  participant Builder as addConstraintFromValues
  participant Query as Parse.Query

  User->>Filter: select "contains substring" constraint
  Filter->>Builder: addConstraintFromValues(field, 'contains', value)
  Builder->>Query: query.contains(field, String(value))
  Query-->>Filter: returns matching records via escaped regex
Loading

Related Issues: #2153

Suggested labels: enhancement, filters

Suggested reviewers: dblythy, mtrezza

🐰 A whisker twitches, sniffing through strings so tight,
No more escaping stray parentheses at night,
"Contains" now means what it plainly should say,
While "matches" keeps its regex power at play,
A tiny carrot of code, tucked in with delight.

🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Engage In Review Feedback ❓ Inconclusive Repo only shows the final feature commit; no review discussion/comment history is present, so feedback engagement can't be verified. Provide PR review thread or evidence of discussion plus follow-up commit/retraction; otherwise this check remains unverifiable.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title uses the required feat: prefix and clearly matches the new String contains-substring filter.
Description check ✅ Passed The description covers the issue, approach, and testing, though it does not follow the template headings exactly.
Linked Issues check ✅ Passed The PR implements #2153 by adding literal contains matching while preserving regex-based matches behavior and adding tests.
Out of Scope Changes check ✅ Passed The changes are limited to the new String contains operator, query handling, and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Security Check ✅ Passed The change only adds a literal substring filter via Parse.Query.contains; the regex path is unchanged and no new unsafe sink is introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@mtrezza

mtrezza commented Jul 5, 2026

Copy link
Copy Markdown
Member

I don't understand what this PR is trying to achieve? What's the purpose of adding a "contains" filter, which was removed in #2991 because it was just a subset of "matches regex"?

@dblythy

dblythy commented Jul 5, 2026

Copy link
Copy Markdown
Member Author

Oh, I didn't realise this previously existed. I thought the ticket was about adding the .contains method that Parse Server support (even in the PR you linked it was a regexp)

FWIW startsWith, endsWith can also just be done with a regexp.

Happy to close though if you prefer

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.

Undocumented regexp matching is confusing

2 participants