Maximum attribute limits and nesting depth in Sanity.io
27 replies
Last updated: Jul 14, 2020
J
Hey! Is there a maximum amount of types you can specify in the
ofattribute of a field with
type: array? Thanks!
Jul 8, 2020, 7:23 PM
P
Hi User! I don’t think there’s an actual limit but things might get a bit cumbersome or slow at some point. However, there is an overall attribute limit of 2000 so adding tons of unique paths (each type will add to this) might bring you closer to that one. More info on limits in general: https://www.sanity.io/docs/technical-limits
You’ll probably be alright though - what’s the use case?
🙂
You’ll probably be alright though - what’s the use case?
🙂
Jul 8, 2020, 10:07 PM
J
It’s a field that allows a list of different building blocks inside. It’s a good point what you’ve raised, as we intended to make the structure some-what recursive with restrictions
Jul 9, 2020, 12:30 PM
J
Definitely we’ll see about these 2.
Maximum number of unique attributes across all documents: 2000 attributes Maximum attribute nesting depth: 20 levels
Jul 9, 2020, 12:31 PM
J
Is there a way to check via CLI or Studio what is the current value of those? To see if that’s a problem before we pivot to a different content model. Does something appear on the Studio as you go over the limits, or does it only happen when importing faulty datasets? If someone is hovering over those values does Sanity contact them or what’s the way to know?
Jul 9, 2020, 12:39 PM
J
Thanks!
Jul 9, 2020, 12:45 PM
P
Regarding attribute nesting, not sure if we have any endpoint with stats on that so it’s probably good to keep an eye out for this yourself, particularly when using nested block content structures for example.
You can monitor your attribute stats via
- check
You can monitor your attribute stats via
<projectId>.<http://api.sanity.io/v1/data/stats/|api.sanity.io/v1/data/stats/><datasetName>
fields.count.value(the one right next to
limit: 2000). You will start seeing errors if you exceed this limit but no warnings when you’re close to it. That’s something we would still like to improve since it’s helpful to get a timely warning, particularly as it relates to content modelling and it can be tricky to change everything after the fact.
Jul 9, 2020, 12:58 PM
J
Thanks!
Jul 9, 2020, 1:09 PM
J
One last thing, for attribute nesting, is there an easy way to check?Document of type… “Section”, has a field content.
section.content.alpha.bravo.charlie.delta.echo.foxtrot.golf.hotel….
Jul 9, 2020, 1:33 PM
J
that’ll be disabled to edit in Studio and/or break an import as those keys become +20?
Jul 9, 2020, 1:34 PM
J
or is there a different calculation here
Jul 9, 2020, 1:34 PM
P
I’d have to check with the team to see how the limit is enforced in this case - do you already have a path with +20 nested keys?
Jul 9, 2020, 1:43 PM
J
One of my colleagues does haha now it makes all sense. As it stopped him from importing a dataset with a JSON that ended up having…
content.0.bars.0.contentBlock.content.list.0.columns.2.contentBlock.content.list.4.columns.2.contentBlock.content.list.0.style.designTokenTypography
Jul 9, 2020, 1:49 PM
J
A bit of an edge case, and we can certainly remove a few to go back to minus 20, but certainly a flag to see if we can save some keys to avoid generating structures that are simple but still nested
Jul 9, 2020, 1:50 PM
P
Indeed, it’s probably a good opportunity to review the content model, as usually getting to the nested keys limit means you’re at risk of approaching the attribute limit as well. Sorry you’re running into this one though.
Jul 9, 2020, 1:54 PM
J
No worries! We love working with Sanity 🙌 . My final question would be… if this content structure is on a documentType1, and on a documentType 2
Jul 9, 2020, 2:04 PM
J
does it generate N attributes or does it count like the same towards the 2000 limit
Jul 9, 2020, 2:04 PM
J
assuming the final key ends up being , does it count as 1 attribute for
contentBlock.content.list.0.columns.2.contentBlock.content.list.4.columns.0.title....
documentType1and 1 more attribute for
documentType2? or is the “top level document type” not part of the unique path used to calculate unique attributes
Jul 9, 2020, 2:05 PM
P
That’s a great question and one I’m not sure about. As far as I know, it looks for similar paths regardless of the enclosing document name but it would be good to put that to the test.
However, the example you give would be more than a single path even if it doesn’t differentiate between the document types. As an example:
This leads to the following six paths (attributes):
However, the example you give would be more than a single path even if it doesn’t differentiate between the document types. As an example:
{ "foo": [ { "bar":…, "baz":… }, { "bar":…, "baz":… }, { "bat": { "bar":… } } ] }
This leads to the following six paths (attributes):
- foo -> an array - foo[] -> an object - foo[].bar -> a string - foo[].baz -> a string - foo[].bat -> an object - foo[].bat.bar -> a string
Jul 9, 2020, 2:44 PM
J
Oh totally, that’s expected. My only concern is whether I can put
instead of N*M (where M is the amount of documents using it) paths
foofields on different documents (As a field of the top level) and still only end up with N paths…
- foo -> an array - foo[] -> an object - foo[].bar -> a string - foo[].baz -> a string - foo[].bat -> an object - foo[].bat.bar -> a string
- documentType1.foo -> an array - documentType1.foo[] -> an object - documentType1.foo[].bar -> a string - documentType1.foo[].baz -> a string - documentType1.foo[].bat -> an object - documentType1.foo[].bat.bar -> a string - documentType2.foo -> an array - documentType2.foo[] -> an object - documentType2.foo[].bar -> a string - documentType2.foo[].baz -> a string - documentType2.foo[].bat -> an object - documentType2.foo[].bat.bar -> a string
Jul 9, 2020, 3:25 PM
P
Fair concern! I’ll check this for you because I’m not actually sure 🙂 Will post back here tomorrow hopefully.
Jul 9, 2020, 3:26 PM
J
Thank you so much!
Jul 9, 2020, 3:29 PM
P
Hi again User, I can confirm you would end up with N*M paths in the above case, so the document types are indeed a multiplier for the number of paths I’m afraid.
Jul 10, 2020, 8:35 AM
J
Hi User, thanks for the answer.
And if
And if
documentType2.foo[].batthere are actually 2 different objects that could use the name
bat(let’s imagine that internal object could have different _type, and has different fields inside), would
documentType2.foo[].batalways count as 1 path? Obviously nested paths would vary.
Jul 10, 2020, 10:26 AM
J
Hi User, thanks so much for all the help! This is being super helpful for us.
Alternatively I’m guessing we could just create the recursion using references to a document (instead of nesting objects directly) which would certainly bring down the total possible paths (exponentially!), but will make reading this considerably harder. Although I think
Let’s go with a basic example:
document 0
document 1
document 2
1.
Would you recommend a strategy like this instead of actually nesting the objects?2.
Alternatively I’m guessing we could just create the recursion using references to a document (instead of nesting objects directly) which would certainly bring down the total possible paths (exponentially!), but will make reading this considerably harder. Although I think
_rawfields with
resolveReferences: { maxDepth: N }should sort it on Gatsby GraphQL and some pretty cool GROQ queries would also work alternatively.
Let’s go with a basic example:
document 0
_type: contentBlock id: 0 content.list.0 // {} object of _type here is one of the many options available, in this case contentItemColumns content.list.0.columns // [] array of refs to type: contentBlock content.list.0.columns.0._ref = 1 content.list.0.columns.1._ref = 2
_type: contentBlock id: 1 content.list.0 // {} object of another _type here, contentItemHeading
_type: contentBlock id: 2 content.list.0 // {} object of another _type here, contentItemImage
Would you recommend a strategy like this instead of actually nesting the objects?2.
content.list.0being a typeof (in JS)
object, despite that on document 0 it is of Sanity
_type contentItemColumns, on document 1 of
_type contentItemHeading, and on document 2
_type contentItemImage– does it count as one unique attribute or does it count as 3 different? Of course that the internal fields of those 3 types would generate unique paths (for example as contentItemColumns has field
columnsand the others don’t), but there’s also an opportunity here if they all have a field called
fooof type
stringand it counts as just 1 unique attribute instead of 3.Thanks for the patience and the great support, I think this is the last bit of information needed for us to take a second step at this and improve our modelling without ever hitting the technical limits!
Jul 10, 2020, 10:27 AM
J
Leaving an update here case in it helps anyone!
I was able to confirm array with multiple types inside (as
I was able to confirm array with multiple types inside (as
of) should count as just one unique path as the path Sanity counts is…
content.list - array content.list[] - object (it doesn't matter if N different types can be this object) content.list[].eachField (here's where having lots of different types would start increasing the possible paths)
Jul 14, 2020, 2:17 PM
J
If you need help reviewing what paths your project is generating…
1. Install
https://www.sanity.io/docs/the-vision-plugin 2. Use the query
4. Use this package
https://www.npmjs.com/package/json-list-paths to do
1. Install
https://www.sanity.io/docs/the-vision-plugin 2. Use the query
*to fetch the entire dataset.3. Copy and save the entire JSON onto your disk
4. Use this package
https://www.npmjs.com/package/json-list-paths to do
jlp(yourJSON).list()It’s a bit off (+-10-20 paths) but it gives you a pretty good understanding!
Jul 14, 2020, 2:19 PM
J
const jlp = require('json-list-paths'); const json = require('./dataset.json'); const result = jlp(json).list(); console.log(result); console.log(`-> There were a total of ${result.length} paths in the JSON.`)
Jul 14, 2020, 2:22 PM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.