Skip to content

Commit eff75f9

Browse files
authored
fix: deep querying, handle getLocalizedPaths for blocks (#10187)
Fixes #10126 Properly handles the `getLocalizedPaths` function for blocks. Previously, using collection with this config: ``` { slug: 'deep-nested', fields: [ { type: 'tabs', tabs: [ { name: 'content', fields: [ { type: 'blocks', name: 'blocks', blocks: [ { slug: 'testBlock', fields: [ { type: 'tabs', tabs: [ { name: 'meta', fields: [ { type: 'relationship', relationTo: 'movies', name: 'movie', }, ], }, ], }, ], }, ], }, ], }, ], }, ], }, ``` The following query didn't work in MongoDB: ```ts const result = await payload.find({ collection: 'deep-nested', where: { 'content.blocks.meta.movie': { equals: movie.id, }, }, }) ```
1 parent ebf3cee commit eff75f9

File tree

4 files changed

+150
-5
lines changed

4 files changed

+150
-5
lines changed

packages/payload/src/database/getLocalizedPaths.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,32 @@ export function getLocalizedPaths({
4545

4646
let fieldsToSearch: FlattenedField[]
4747

48-
if (lastIncompletePath?.field && 'flattenedFields' in lastIncompletePath.field) {
49-
fieldsToSearch = lastIncompletePath.field.flattenedFields
48+
let matchedField: FlattenedField
49+
50+
if (lastIncompletePath?.field?.type === 'blocks') {
51+
if (segment === 'blockType') {
52+
matchedField = {
53+
name: 'blockType',
54+
type: 'text',
55+
}
56+
} else {
57+
for (const block of lastIncompletePath.field.blocks) {
58+
matchedField = block.flattenedFields.find((field) => field.name === segment)
59+
if (matchedField) {
60+
break
61+
}
62+
}
63+
}
5064
} else {
51-
fieldsToSearch = lastIncompletePath.fields
65+
if (lastIncompletePath?.field && 'flattenedFields' in lastIncompletePath.field) {
66+
fieldsToSearch = lastIncompletePath.field.flattenedFields
67+
} else {
68+
fieldsToSearch = lastIncompletePath.fields
69+
}
70+
71+
matchedField = fieldsToSearch.find((field) => field.name === segment)
5272
}
5373

54-
const matchedField = fieldsToSearch.find((field) => field.name === segment)
5574
lastIncompletePath.field = matchedField
5675

5776
if (currentPath === 'globalType' && globalSlug) {
@@ -94,7 +113,6 @@ export function getLocalizedPaths({
94113
}
95114

96115
switch (matchedField.type) {
97-
case 'blocks':
98116
case 'json':
99117
case 'richText': {
100118
const upcomingSegments = pathSegments.slice(i + 1).join('.')

test/relationships/config.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,47 @@ export default buildConfigWithDefaults({
387387
},
388388
],
389389
},
390+
{
391+
slug: 'deep-nested',
392+
fields: [
393+
{
394+
type: 'tabs',
395+
tabs: [
396+
{
397+
name: 'content',
398+
fields: [
399+
{
400+
type: 'blocks',
401+
name: 'blocks',
402+
blocks: [
403+
{
404+
slug: 'testBlock',
405+
fields: [
406+
{
407+
type: 'tabs',
408+
tabs: [
409+
{
410+
name: 'meta',
411+
fields: [
412+
{
413+
type: 'relationship',
414+
relationTo: 'movies',
415+
name: 'movie',
416+
},
417+
],
418+
},
419+
],
420+
},
421+
],
422+
},
423+
],
424+
},
425+
],
426+
},
427+
],
428+
},
429+
],
430+
},
390431
],
391432
onInit: async (payload) => {
392433
await payload.create({

test/relationships/int.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,38 @@ describe('Relationships', () => {
363363
expect(docs[0].id).toBe(doc.id)
364364
})
365365

366+
it('should allow querying within tabs-blocks-tabs', async () => {
367+
const movie = await payload.create({ collection: 'movies', data: { name: 'Pulp Fiction' } })
368+
369+
const { id } = await payload.create({
370+
collection: 'deep-nested',
371+
data: {
372+
content: {
373+
blocks: [
374+
{
375+
blockType: 'testBlock',
376+
meta: {
377+
movie: movie.id,
378+
},
379+
},
380+
],
381+
},
382+
},
383+
})
384+
385+
const result = await payload.find({
386+
collection: 'deep-nested',
387+
where: {
388+
'content.blocks.meta.movie': {
389+
equals: movie.id,
390+
},
391+
},
392+
})
393+
394+
expect(result.totalDocs).toBe(1)
395+
expect(result.docs[0].id).toBe(id)
396+
})
397+
366398
describe('Custom ID', () => {
367399
it('should query a custom id relation', async () => {
368400
const { customIdRelation } = await restClient

test/relationships/payload-types.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface Config {
2828
'rels-to-pages': RelsToPage;
2929
'rels-to-pages-and-custom-text-ids': RelsToPagesAndCustomTextId;
3030
'object-writes': ObjectWrite;
31+
'deep-nested': DeepNested;
3132
users: User;
3233
'payload-locked-documents': PayloadLockedDocument;
3334
'payload-preferences': PayloadPreference;
@@ -52,6 +53,7 @@ export interface Config {
5253
'rels-to-pages': RelsToPagesSelect<false> | RelsToPagesSelect<true>;
5354
'rels-to-pages-and-custom-text-ids': RelsToPagesAndCustomTextIdsSelect<false> | RelsToPagesAndCustomTextIdsSelect<true>;
5455
'object-writes': ObjectWritesSelect<false> | ObjectWritesSelect<true>;
56+
'deep-nested': DeepNestedSelect<false> | DeepNestedSelect<true>;
5557
users: UsersSelect<false> | UsersSelect<true>;
5658
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
5759
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
@@ -350,6 +352,27 @@ export interface ObjectWrite {
350352
updatedAt: string;
351353
createdAt: string;
352354
}
355+
/**
356+
* This interface was referenced by `Config`'s JSON-Schema
357+
* via the `definition` "deep-nested".
358+
*/
359+
export interface DeepNested {
360+
id: string;
361+
content?: {
362+
blocks?:
363+
| {
364+
meta?: {
365+
movie?: (string | null) | Movie;
366+
};
367+
id?: string | null;
368+
blockName?: string | null;
369+
blockType: 'testBlock';
370+
}[]
371+
| null;
372+
};
373+
updatedAt: string;
374+
createdAt: string;
375+
}
353376
/**
354377
* This interface was referenced by `Config`'s JSON-Schema
355378
* via the `definition` "payload-locked-documents".
@@ -425,6 +448,10 @@ export interface PayloadLockedDocument {
425448
relationTo: 'object-writes';
426449
value: string | ObjectWrite;
427450
} | null)
451+
| ({
452+
relationTo: 'deep-nested';
453+
value: string | DeepNested;
454+
} | null)
428455
| ({
429456
relationTo: 'users';
430457
value: string | User;
@@ -667,6 +694,33 @@ export interface ObjectWritesSelect<T extends boolean = true> {
667694
updatedAt?: T;
668695
createdAt?: T;
669696
}
697+
/**
698+
* This interface was referenced by `Config`'s JSON-Schema
699+
* via the `definition` "deep-nested_select".
700+
*/
701+
export interface DeepNestedSelect<T extends boolean = true> {
702+
content?:
703+
| T
704+
| {
705+
blocks?:
706+
| T
707+
| {
708+
testBlock?:
709+
| T
710+
| {
711+
meta?:
712+
| T
713+
| {
714+
movie?: T;
715+
};
716+
id?: T;
717+
blockName?: T;
718+
};
719+
};
720+
};
721+
updatedAt?: T;
722+
createdAt?: T;
723+
}
670724
/**
671725
* This interface was referenced by `Config`'s JSON-Schema
672726
* via the `definition` "users_select".

0 commit comments

Comments
 (0)