fix: querying hasMany: true select fields inside polymorphic joins (#13334)

This PR fixes queries like this:

```ts
const findFolder = await payload.find({
  collection: 'payload-folders',
  where: {
    id: {
      equals: folderDoc.id,
    },
  },
  joins: {
    documentsAndFolders: {
      limit: 100_000,
      sort: 'name',
      where: {
        and: [
          {
            relationTo: {
              equals: 'payload-folders',
            },
          },
          {
            folderType: {
              in: ['folderPoly1'], // previously this didn't work
            },
          },
        ],
      },
    },
  },
})
```

Additionally, this PR potentially fixes querying JSON fields by the top
level path, for example if your JSON field has a value like: `[1, 2]`,
previously `where: { json: { equals: 1 } }` didn't work, however with a
value like `{ nested: [1, 2] }` and a query `where: { 'json.nested': {
equals: 1 } }`it did.

---------

Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
Sasha
2025-07-30 22:30:20 +03:00
committed by GitHub
parent 3114b89d4c
commit b26a73be4a
5 changed files with 137 additions and 13 deletions

View File

@@ -60,6 +60,10 @@ const createConstraint = ({
formattedOperator = '='
}
if (pathSegments.length === 1) {
return `EXISTS (SELECT 1 FROM json_each("${pathSegments[0]}") AS ${newAlias} WHERE ${newAlias}.value ${formattedOperator} '${formattedValue}')`
}
return `EXISTS (
SELECT 1
FROM json_each(${alias}.value -> '${pathSegments[0]}') AS ${newAlias}
@@ -68,21 +72,38 @@ const createConstraint = ({
}
export const createJSONQuery = ({
column,
operator,
pathSegments,
rawColumn,
table,
treatAsArray,
treatRootAsArray,
value,
}: CreateJSONQueryArgs): string => {
if ((operator === 'in' || operator === 'not_in') && Array.isArray(value)) {
let sql = ''
for (const [i, v] of value.entries()) {
sql = `${sql}${createJSONQuery({ column, operator: operator === 'in' ? 'equals' : 'not_equals', pathSegments, rawColumn, table, treatAsArray, treatRootAsArray, value: v })} ${i === value.length - 1 ? '' : ` ${operator === 'in' ? 'OR' : 'AND'} `}`
}
return sql
}
if (treatAsArray?.includes(pathSegments[1]!) && table) {
return fromArray({
operator,
pathSegments,
table,
treatAsArray,
value,
value: value as CreateConstraintArgs['value'],
})
}
return createConstraint({ alias: table, operator, pathSegments, treatAsArray, value })
return createConstraint({
alias: table,
operator,
pathSegments,
treatAsArray,
value: value as CreateConstraintArgs['value'],
})
}