List Elements
A listElement reference says the value must be one of the identifiers a list on another document holds. inList names the list, and the $id pair of propertyAgreement names the document holding it. Reach for it when membership is written down once as a list on a document that never changes, such as the members elected with a charter, and other documents must name one of them.
| Where | refersTo on an identifier property, or on the items of a typed array of identifiers, where every element must be listed; an operand of an expression; or ownerRefersTo and creatorRefersTo, where the writer or the creator must be listed. |
| Value | "type": "listElement" with documentType (the type holding the list), propertyAgreement (exactly one pair with $id on its referenced side, and up to nine other pairs), inList (the path of a typed array of identifiers on that type), and optionally contractId. |
| Since | protocol version 14 |
| On update | Fixed, like the rest of refersTo (IncompatibleDocumentTypeSchemaError, 10246). |
| Errors | ReferencedEntityNotFoundError (40120) when the value is not in the list or the list's document is not found; ReferencedDocumentPropertyMismatchError (40127) for another pair; at registration ReferencedDocumentListInvalidError (40138) for a list of another contract. |
Example
The moderation charters contract lets the leader of a seated team take an elected member off it with a removedModerator document:
"removedModerator": {
"type": "object",
"documentsMutable": false,
"canBeDeleted": true,
"properties": {
"electedCharterId": {
"type": "array", "byteArray": true, "minItems": 32, "maxItems": 32,
"contentMediaType": "application/x.dash.dpp.identifier",
"refersTo": {
"type": "permanentDocument",
"documentType": "electedCharter",
"propertyAgreement": { "$ownerId": "$ownerId" }
},
"position": 0
},
"memberId": {
"type": "array", "byteArray": true, "minItems": 32, "maxItems": 32,
"contentMediaType": "application/x.dash.dpp.identifier",
"distinctFrom": "$ownerId",
"refersTo": {
"type": "listElement",
"documentType": "electedCharter",
"propertyAgreement": { "electedCharterId": "$id" },
"inList": "members"
},
"position": 1
}
},
"required": ["$createdAt", "electedCharterId", "memberId"],
"additionalProperties": false
}
electedCharterId must name an elected charter the writer owns, so only the team's leader can write one. memberId must be one of the members of the electedCharter document whose $id this document's electedCharterId holds, so only an elected member can be removed. electedCharter is immutable and can never be deleted, so its members never change.
How it works
When the referring document is created or replaced:
- The document holding the list is the one whose
$idequals the value of the$idpair's referring property. It is fetched by id, once per write: in the example theelectedCharterIdreference and the list reference share one fetch. The list is collected once, so checking many values against it costs one read. - The other
propertyAgreementpairs are checked against that document, as for any document reference (ReferencedDocumentPropertyMismatchError, 40127). - The value must be in the list. On a typed array every element must be; on the writer's or creator's reference, the writer or creator must be.
A value not in the list, a list document that does not exist, or a value set while the $id property is not, refuses the write with ReferencedEntityNotFoundError (40120), naming the property, or an element by its list path (memberIds[1] for the second):
electedCharter 7kX...: members [Alice, Bob]
removedModerator { electedCharterId: 7kX..., memberId: Alice } -> accepted
removedModerator { electedCharterId: 7kX..., memberId: Carol } -> refused, 40120:
referenced list element (members of the electedCharter document electedCharterId names)
<Carol> not found for path memberId
A replace checks the reference again when its value changed, or when the referring side of any of its pairs changed: the $id property among them, since it may now name another document, whose list is then checked against every value. A pair keyed by $ownerId is checked on every replace. When only a typed array of values changed, the elements the stored list already held are not checked again. Nothing else can make a validated value unlisted: the list's document is never deleted and its list never changes.
Rules at registration
propertyAgreementholds exactly one pair with$idon the referenced side. Its referring side is an identifier property of the referring document type: not$ownerId(no document has the writer's id) and not a typed array (one document holds the list). It must be stored, so it and every object around it are nottransient, and a reader can tell from the stored document which list the value was checked against. It may be optional. It needs norefersToof its own; if it has one, that must be a reference by id todocumentTypein the list's contract, or the pair could never hold. Refused withInvalidContractStructure(10231) otherwise.- The other pairs follow the rules of every
propertyAgreement(ReferencedDocumentPropertyAgreementInvalidError, 40126). documentTypemust exist (ReferencedDocumentTypeNotFoundError, 40121), and its documents must never disappear:canBeDeleted: false, nomoderatorAbilities.deleteand nottl.inListis a property path (a dotted one for a nested list, never a$name) of a stored typed array of identifiers ondocumentType, and the list must be fixed once a document is written: the type is immutable (documentsMutable: false), or the list's top-level property is listed underimmutable. A list that is also underimmutableAllowSettingqualifies, since it can only be set once on a document that had none, and an absent list accepted no value.- The checks on
documentTypeandinListare refused withInvalidContractStructure(10231) for a document type of the declaring contract. For one of another contract, a deletable type is refused withReferencedDocumentTypeDeletableError(40122) and a list that does not qualify withReferencedDocumentListInvalidError(40138). - Each value counts one against the reference budget,
maxItemsfor a typed array.
See also
- References (refersTo) for
documentType,contractId,propertyAgreementand the replace rules. - Expressions and Writer and Creator References, where a list element is a common operand or target.
- An element of a list in the Documents chapter, with the internals.
- Typed Arrays and Mutability for the list and the rules that keep it fixed.