feat(query): port TextQuery per-token and per-field weights (#17)#32
Draft
ajGingrich wants to merge 7 commits into
Draft
feat(query): port TextQuery per-token and per-field weights (#17)#32ajGingrich wants to merge 7 commits into
ajGingrich wants to merge 7 commits into
Conversation
- Widen textFieldName to string | Record<string, number> - Expose fieldWeights as a frozen readonly record - Validate weights are finite numbers > 0 - Reject empty records, arrays, non-string keys Renders unchanged for now; multi-field rendering follows.
- Emit one clause per field, OR-joined when multi-field
- Omit => { $weight } when weight is exactly 1.0
- Wrap multi-field clauses in parens
- Preserve filter AND-wrapping
- Accept textWeights record; lowercase + trim keys at construction
- Reject keys with inner whitespace, negative/NaN/Infinity weights
- Allow weight of 0 for tokens (suppresses scoring contribution)
- Render matched tokens as token=>{$weight:N} inside the OR list
- Match keys case-insensitively against normalized query tokens
- Return bare string when single field has weight 1.0 - Return shallow copy of fieldWeights record otherwise - Mirror Python query.py:1510-1521 for cross-language compatibility
- Update class JSDoc with per-field and per-token weight examples - Remove stale "not yet ported" note - Add user-guide subsection covering both forms with rendered output - Document intentional mutator divergence from Python
- Seed two docs with matching terms in different text fields - Query with per-field weights heavily favoring one field - Assert the doc whose match is in the higher-weighted field ranks first
- Add JSDoc to fieldWeights and textWeights field declarations covering frozen-at-construction, insertion-order render semantics, and null-prototype - Surface a clearer "textFieldName is required" error when the property is omitted or null (previously fell through to the generic shape error) - Tighten the missing-textFieldName test to assert the message
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #17.
Summary
Brings TS
TextQueryto parity with Python redisvl on text weighting:textFieldNamenow acceptsstring | Record<string, number>.textWeights?: Record<string, number>for per-token bias.=> { $weight: N }syntax (dialect 2).readonly— no mutators (intentional divergence from Python; documented).Stacked on #31
This PR is based on
feat/textquery-stopwords-16(PR #31, stopwords port). The base branch is set to that PR so GitHub displays a clean diff. Do not merge until #31 lands. I will rebase ontomainand undraft once that happens.Behavior
textFieldName: 'd'@d:(quick | fox)(unchanged)textFieldName: { title: 5 }@title:(quick | fox) => { $weight: 5 }textFieldName: { title: 3, body: 1 }(@title:(quick | fox) => { $weight: 3 } | @body:(quick | fox))textWeights: { apple: 2 }@d:(apple=>{$weight:2} | pear)Tokens are lowercased before
textWeightslookup (Python parity, leverages PR #31's normalization pipeline). Parsers useObject.create(null)so adversarial query tokens likeconstructoror__proto__cannot resolve through the prototype chain.What's covered
src/query/text.ts— widened config, parsers, render logic, JSDoc.tests/unit/query/text.test.ts— new tests for field weights, text weights, validation, render output, Python-compattextFieldNamegetter, prototype-pollution regression.tests/integration/query-types.test.ts— multi-field weighted ranking against a real Redis container.website/docs/user-guide/filters-and-queries.md— weighting subsection.Out of scope (intentional)
setFieldWeights,setTextWeights) — TS port stays readonly.Verification
Test plan
textFieldNamePython-compat getter shape is desiredReference
Python redisvl:
redisvl/query/query.py:1273-1589.🤖 Generated with Claude Code