Defining Nested JSON Schema for Querying
TLDR Greg struggled in defining a schema for querying a JSON object with nested fields. Jason offered solutions, with the final resolution involving the use of "object" as a field type for the contributors in the schema.




Sep 29, 2022 (12 months ago)
Greg
09:34 PM{
...
"contributors": {
"contributor1": {
"bio": "Something about this author",
"firstName": "Lewis",
"lastName": "Carroll",
"type": "author"
}
"contributor2": ...
"contributorX": ...
}
...
}
It can have an unknown number of contributors. How do I define the schema for that? I am going to have to query by a contributors first & last name, type, and be able to group by the author.
Jason
09:36 PM{
...
"contributors": [
{
"bio": "Something about this author",
"firstName": "Lewis",
"lastName": "Carroll",
"type": "author"
},
{ ... },
{ ... }
]
...
}
Greg
09:37 PMGreg
09:41 PMJason
09:41 PM{
"name": "collection_name",
"fields": [
{"name": "contributors\..*.firstName", "type": "auto" },
{"name": "contributors\..*.lastName", "type": "auto" },
{"name": "contributors\..*.type", "type": "auto" },
]
}
Jason
09:42 PMGreg
09:43 PMGreg
09:47 PM {
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributors..*.firstName",
"nested": false,
"optional": true,
"sort": false,
"type": "string"
},
{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributors..*.lastName",
"nested": false,
"optional": true,
"sort": false,
"type": "string"
},
{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributors..*.type",
"nested": false,
"optional": true,
"sort": false,
"type": "string"
},
However, I can’t query by those fields in the typesense UI. I am going to try it in code.
Jason
09:48 PMGreg
09:48 PMGreg
09:48 PMJason
09:48 PMJason
09:48 PMGreg
09:49 PMGreg
09:58 PMcontributors
?Jason
09:59 PMGreg
09:59 PM{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributor..*.firstName",
"nested": false,
"optional": true,
"sort": false,
"type": "auto"
},
{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributor..*.lastName",
"nested": false,
"optional": true,
"sort": false,
"type": "auto"
},
{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "contributor..*.type",
"nested": false,
"optional": true,
"sort": false,
"type": "auto"
},
This is the record in the Typesense :
contributors
{ "contributor1": { "firstName": "Lewis", "lastName": "Carroll", "type": "Author" }, "contributor2": { "firstName": "Greg", "lastName": "Mascherino", "type": "Illustrator" } }
Greg
10:00 PMJason
10:00 PM{
"name": "collection_name",
"enable_nested_fields": true, // <=== this is required
"fields": [
{"name": "contributors\..*.firstName", "type": "auto" },
{"name": "contributors\..*.lastName", "type": "auto" },
{"name": "contributors\..*.type", "type": "auto" },
]
}
Greg
10:03 PMexports.bookContentsSchema = {
name: 'book-contents',
enabled_nested_fields: true,
fields: [
{
facet: false,
name: 'ageDemographicFrom',
optional: true,
type: 'int32',
},
{
facet: false,
name: 'ageDemographicTo',
Result in Typesense clould:
{
"created_at": 1664488909,
"default_sorting_field": "",
"enable_nested_fields": false,
"fields": [
{
"facet": false,
"index": true,
"infix": false,
"locale": "",
"name": "ageDemographicFrom",
"nested": false,
"optional": true,
"sort": true,
Jason
10:04 PMenable_nested_fields
not enabled_nested_fields
Greg
10:05 PMJason
10:06 PMGreg
10:09 PM{
"code": 404,
"error": "Could not find a field named `contributors..*.firstName` in the schema."
}
Greg
10:10 PMGreg
10:11 PMGreg
10:11 PM“code”: 404,
“error”: “Could not find a field named
contributor..*.firstName
in the schema.”}
Jason
10:17 PMJason
10:19 PMquery_by: contributors.contributor1.firstName, contributors.contributor2.firstName,...
Jason
10:19 PMGreg
10:21 PMGreg
10:26 PMGreg
10:26 PM“code”: 404,
“error”: “Could not find a field named
contributors.contributor1.firstName
in the schema.”}
Jason
10:26 PMGreg
10:27 PMexports.bookContentsSchema = {
name: 'book-contents',
enable_nested_fields: true,
fields: [
{
facet: false,
name: 'ageDemographicFrom',
optional: true,
type: 'int32',
},
{
facet: false,
name: 'ageDemographicTo',
optional: true,
type: 'int32',
},
{
facet: false,
name: 'bisac1',
optional: true,
type: 'string',
},
{
facet: false,
name: 'bisac2',
optional: true,
type: 'string',
},
{
facet: false,
name: 'bisac3',
optional: true,
type: 'string',
},
{
facet: false,
name: 'chunk',
optional: false,
type: 'string',
},
{
facet: false,
name: 'cfi',
optional: false,
type: 'string',
},
{
name: 'contributor..*.firstName',
type: 'auto',
},
{
name: 'contributor..*.lastName',
type: 'auto',
},
{
name: 'contributor..*.type',
type: 'auto',
},
{
facet: false,
name: 'genres',
optional: true,
type: 'string[]',
},
{
facet: true,
name: 'isbn',
optional: false,
type: 'string',
},
{
facet: false,
name: 'keywords',
optional: true,
type: 'string[]',
},
{
facet: false,
name: 'pageCount',
optional: true,
type: 'int32',
},
{
facet: false,
name: 'physicalCopyLink',
optional: true,
type: 'string',
},
{
facet: false,
name: 'publicationDate',
optional: true,
type: 'int64',
},
{
facet: false,
name: 'published',
optional: true,
type: 'bool',
},
{
facet: false,
name: 'subtitle',
optional: true,
type: 'string',
},
{
facet: false,
name: 'thumbnail',
optional: true,
type: 'string',
},
{
facet: false,
name: 'title',
optional: false,
type: 'string',
},
],
};
Jason
10:27 PMGreg
10:27 PMGreg
10:28 PM const searchParameters = {
searches: [
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'title',
},
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'subtitle',
},
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'keywords',
},
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'genres',
},
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'isbn',
},
{
query_by: 'contributors.contributor1.firstName',
per_page: 5,
},
{
group_by: 'isbn',
group_limit: 1,
per_page: 5,
query_by: 'chunk',
},
],
};
const commonSearchParameters = {
collection: 'book-contents',
q: e.target.value,
};
typesenseClient.multiSearch
.perform(searchParameters, commonSearchParameters)
.then((response) => {
setSearchResults(response);
})
.catch((error) => {
console.error(error);
});
Greg
10:29 PMJason
10:29 PM"name": "contributor..*.firstName"
Should be:
"name": "contributors..*.firstName"
Greg
10:30 PMGreg
10:30 PM{ “contributor1”: { “firstName”: “Lewis”, “lastName”: “Carroll”, “type”: “Author” }, “contributor2": { “firstName”: “Greg”, “lastName”: “Mascherino”, “type”: “Illustrator” } }
Greg
10:30 PMJason
10:30 PMJason
10:30 PM{
"name": "collection_name",
"enable_nested_fields": true,
"fields": [
{"name": "contributors", "type": "object" }
]
}
Jason
10:31 PMcontributors
is the top level fieldGreg
10:32 PMJason
10:33 PMGreg
10:39 PM
Greg
10:44 PM


Typesense
Indexed 2764 threads (79% resolved)
Similar Threads
Troubleshooting Typesense Search in Nested Fields
Vadali couldn't search within nested artist.name field. Kishore Nallan helped diagnose and fix, which involved updating their cloud cluster to a later version. Jason provided advice on using the correct Docker image.

Troubleshooting Query Error with Optional Nested Objects
Jordan encountered an error while querying optional nested objects. Jason suggested ensuring at least one document has the field or defining fields explicitly in the schema.

Accessing Nested Objects Using `query_by` in Typesense
Emma wanted to query nested objects using `query_by`. Kishore Nallan suggested using `title.*` pattern and ensuring `enable_nested_fields` is set to true.



Troubleshooting Issues with DocSearch Hits and Scraper Configuration
Rubai encountered issues with search result priorities and ellipsis. Jason helped debug the issue and suggested using different versions of typesense-docsearch.js, updating initialization parameters, and running the scraper on a Linux-based environment. The issues related to hits structure and scraper configuration were resolved.



Resolving Typesense Analytics "top_queries" Collection Issue
Zain faced issues with typesense analytics and an empty "top_queries" collection. Jason and Kishore Nallan assisted in troubleshooting, identified a bug, and suggested a fix in `0.25.0.rc66`. The fix worked for Zain.
