domino-db Document Schema
The domino-db module represents a document as a JavaScript object. The exact structure of the object varies with the items on the document. In other words, the object structure is application specific. There are rules for converting each document item to JavaScript, but before we describe the rules, it's useful to start with an example.
domino-db documents by example
Let’s say you have a document representing contact information. The form name is "Contact", and the document includes the following TEXT items: FirstName, LastName, City, and State. When you use domino-db to read this document, you get an object like this:
{
'@unid': '4A51270A49D9C592852582DA0055D63F',
'@created': {
type: 'datetime',
data: '2018-07-30T15:37:34.07Z'
},
'@modified': {
type: 'datetime',
data: '2018-07-30T15:37:35.09Z'
},
Form: 'Contact',
FirstName: 'Edwin',
LastName: 'Moody',
City: 'Toledo',
State: 'OH'
}
The first thing you will notice is that some property names begin with "@".
These are system properties. For example, the @unid
property represents the
UNID of the document, and @created
represents the date the document was
created. System properties represent document metadata. When you use domino-db
to create or update a document, the system properties are ignored. In other
words, you cannot assign or change a document UNID or created date. For more
details, see System properties.
In the above example, the Form
, FirstName
, LastName
, City
, and State
properties map directly to application-specific items on the document. Obviously
these properties make sense for a contact document. You would get a different
set of properties if you read another type of document. For example, an object
representing a mail message would have properties named Subject
, From
, and
SendTo
-– just to name a few properties.
Item property schema
The canonical format for an item property is as follows:
<item-name>: {
type: <item-type>,
data: <item-data>,
nonsummary: <nonsummary-flag>,
encrypt: <encrypt-flag>,
names: <names-flag>,
readers: <readers-flag>,
authors: <authors-flag>,
}
where:
<item-name>
is the corresponding item name.<item-type>
is a string indicating the item type. Legal values include'text'
,'number'
,'datetime'
, and'reference'
. This version of domino-db doesn't include support for MIME, rich text and other "advanced" item types.<item-data>
is a string, number, or array representing the item data.<nonsummary-flag>
is a boolean value,true
if the corresponding item does not contain summary data. When omitted the default value isfalse
.<encrypt-flag>
is a boolean value,true
if the item is encrypted. When omitted the default value isfalse
.<names-flag>
is a boolean value,true
if the item contains one or more names. When omitted the default value isfalse
.<readers-flag>
is a boolean value,true
if the item contains the name of one or more readers. When omitted the default value isfalse
.<authors-flag>
is a boolean value,true
if the item is contains the name of one or more authors. When omitted the default value isfalse
.
For example, the following property represents a DATETIME item:
Date: {
type: 'datetime',
data: '2013-03-01T14:09:01Z'
}
And the following represents a DATETIME_LIST:
Dates: {
type: 'datetime',
data: [
'2013-03-01T14:00:00Z',
'2013-03-02T15:00:00Z',
'2013-03-03T16:00:00Z'
]
}
If you want be rigorously consistent, you could represent a TEXT and TEXT_LIST item like this:
Genus: {
type: 'text',
data: 'Panthera'
},
Species: {
type: 'text',
data: ['Lion', 'Tiger', 'Leopard']
}
The above example is perfectly legal, but it can be simpler to imply the type of TEXT and TEXT_LIST items like this:
Genus: 'Panthera',
Species: ['Lion', 'Tiger', 'Leopard']
The previous two examples are functionally equivalent, but the second form is much simpler to use in practice. In other words, the simple format can be defined as:
<item-name>: <item-data>
where:
<item-name>
is the corresponding item name.<item-data>
is a string, number, or array representing the item data.<item-type>
is inferred from<item-data>
.<nonsummary-flag>
is assumed to befalse
.<encrypt-flag>
is assumed to befalse
.<names-flag>
is assumed to befalse
.<readers-flag>
is assumed to befalse
.<authors-flag>
is assumed to befalse
.
It's important to understand you can use this simple format only for 'text'
and 'number'
item types. It does not work for the 'datetime'
and 'reference'
types. Also, you cannot use the simple format for encrypted, nonsummary and
names items.
NOTE: When you use the canonical format:
- the
encrypt
property corresponds to the ITEM_SEAL flag- the
nonsummary
property is the inverse of the ITEM_SUMMARY flag.- the
names
property corresponds to the ITEM_NAMES flag- the
readers
property corresponds to the ITEM_READERS flag- the
authors
property corresponds to the ITEM_READWRITERS flag
Reading items in canonical format
When reading items from one or more documents, you can optionally include the
canonicalFormat: true
value in the options
object to have domino-db return
the item properties in the rigorously consistent canonical format described in
the section above. All items are returned as objects, including at a minimum
type
and data
properties.
Note that the nonsummary
, encrypt
, names
, readers
, and authors
properties are only included in the returned object if they have a value of
true
, and are omitted if they have a value of false
.
For example, suppose a document object named exampleDoc
contains the Genus
and Species
items, neither of which incude any flags. Reading the items with
exampleDoc.read()
returns the following item properties:
Genus: 'Panthera',
Species: ['Lion', 'Tiger', 'Leopard']
Reading the items with exampleDoc.read({ canonicalFormat: true })
returns the
following item properties:
Genus: {
type: 'text',
data: 'Panthera'
},
Species: {
type: 'text',
data: ['Lion', 'Tiger', 'Leopard']
}
Duplicate items
A document can contain two or more items with the same name. These items are referred to as duplicate items, and are differentiated by internal ID numbers. domino-db's default behavior when attempting to read duplicate items is to only return the item with the highest ID.
To return all duplicate items when reading items, include the
duplicateItems: true
value in the options
object. Items are returned in
canonical format as objects (similar to the canonicalFormat: true
value), with
any duplicate items returned as an array of objects.
You can also use duplicateItems: true
to create duplicate items as part of a
request to create or replace documents, or to replace items in documents.
Include duplicateItems: true
in the options
object and specify the duplicate
item as an array at the top level of an item property. An array at the top level
now indicates a duplicate item, rather than a list. The items are created such
that the first element in the array has a duplicate item ID of 0, the second has
a duplicate item ID of 1, and so on.
To create a list (TEXT_LIST, DATETIME_LIST, NUMBER_LIST, NOTEREF_LIST) in combination with this value, represent the list in canonical format. Only arrays at the top level of item properties are treated as an intent to create duplicate items. When adding a list as a duplicate item, both the simple format and the canonical format are allowed.
NOTE: When you replace or delete an item, any duplicates of the item are also deleted before a new item is inserted. To keep duplicate items, use
duplicateItems: true
and include the duplicates in the request.
For example, to remove any items with the name Genus
and create two new items
named Genus
in a document object named exampleDoc
, you could use the
following call:
exampleDoc.replaceItems({
replaceItems: {
Genus: [ 'Panthera', 'Leopardus' ],
},
duplicateItems: true,
});
If you then read the items with exampleDoc.read({ duplicateItems: true })
,
these item properties are returned:
Genus: [
{
type: 'text',
data: 'Panthera'
},
{
type: 'text',
data: 'Leopardus'
}
]
To replace the second Genus
item with a TEXT_LIST and add a Species
item
that is also a TEXT_LIST, use the following call:
exampleDoc.replaceItems({
replaceItems: {
Genus: [
'Panthera',
['Leopardus', 'Lynx', 'Puma']
],
Species: {
type: 'text',
data: ['Lion', 'Tiger', 'Leopard', 'Puma']
}
},
duplicateItems: true,
});
A subsequent exampleDoc.read({ duplicateItems: true })
call returns the
following item properties:
Genus: [
{
type: 'text',
data: 'Panthera'
},
{
type: 'text',
data: ['Leopardus', 'Lynx', 'Puma']
}
],
Species: {
type: 'text',
data: ['Lion', 'Tiger', 'Leopard', 'Puma']
}
Property examples by item type
TEXT
Simple format:
Genus: 'Panthera',
Canonical format:
Genus: {
type: 'text',
data: 'Panthera',
encrypt: true
}
Description: {
type: 'text',
data: 'Some very large string',
nonsummary: true
}
TEXT_LIST
Simple format:
Species: ['Lion', 'Tiger', 'Leopard'],
Canonical format:
Species: {
type: 'text',
data: ['Lion', 'Tiger', 'Leopard'],
encrypt: true
}
Readers list granting access to Joe Smith and anyone with the [Approver] role in the database ACL:
Readers: {
type: 'text',
data: ['CN=Joe Smith/O=Renovations', '[Approver]'],
names: true,
readers, true
}
NOTE: For more details see Names, Readers and Authors items
DATETIME
Date and time:
Datetime: {
type: 'datetime',
data: '2013-03-01T14:09:01Z'
}
Date only:
Date: {
type: 'datetime',
data: '2018-12-11'
}
Time only:
Time: {
type: 'datetime',
data: '15:30:00'
}
NOTE: For more details on the way domino-db represents a DATETIME item, see Datetime values
DATETIME_LIST
Dates: {
type: 'datetime',
data: [
'2013-03-01T14:00:00Z',
'2013-03-02T15:00:00Z',
'2013-03-03T16:00:00Z'
]
}
DATETIME_PAIRS
DatePairs: {
type: 'datetime',
data: [
['2013-03-01T14:00:00Z', '2013-03-02T15:00:00Z'],
['2013-03-03T16:00:00Z', '2013-03-02T17:00:00Z']
]
}
NUMBER
Simple format:
Number: 999,
Canonical format:
Number: {
type: 'number',
data: 999,
nonsummary: true
}
NUMBER_LIST
Simple format:
Numbers: [997, 998, 999],
Canonical format:
Numbers: {
type: 'number',
data: [997, 998, 999],
nonsummary: true
}
NUMBER_PAIRS
Simple format:
NumberPairs: [[997, 998], [999, 1000]],
Canonical format:
NumberPairs: {
type: 'number',
data: [
[997, 998],
[999, 1000]
],
nonsummary: true
}
NOTEREF_LIST
Canonical format:
$REF: {
type: 'reference',
data: ['D375A244ECA1BA688525839A006A4740']
}
By convention, a response document includes a $REF
item of type
NOTEREF_LIST. The above example shows the $REF
item for a response to
a document whose UNID is D375A244ECA1BA688525839A006A4740
. However, a
reference item may include more than one UNID:
Citations: {
type: 'reference',
data: [
'FFFFA244ECA1BA68FFFF839A006A4740',
'D375FFFFECA1BA688525FFFF006A4740',
'D375A244FFFFBA688525839AFFFF4740'
]
}
NOTE: Reference item data is always represented as a list -- even when the list contains one element as in the
$REF
example above.
Datetime values
You might wonder why domino-db doesn't simply use a JavaScript Date
to
represent a Domino DATETIME. The answer is you cannot reliably convert a
DATETIME to a Date
(and vice versa). There are at least three differences
between the two types:
- A Domino DATETIME is only precise to a hundredth of a second. A JavaScript
Date
is more precise -- to the millisecond. - A Domino DATETIME can contain a date only (no time).
- A Domino DATETIME can contain a time only (no date).
Since you cannot reliably convert between the two types, domino-db represents
each DATETIME value as a JavaScript object with a type
of 'datetime'
--
for example:
// Date and time
Datetime: {
type: 'datetime',
data: '2013-03-01T14:09:01.01Z'
},
// Date only
Date: {
type: 'datetime',
data: '2018-12-11'
},
// Time only
Time: {
type: 'datetime',
data: '15:30:00.01'
}
Of course, there may be situations where your application needs to convert
between a JavaScript Date
and a Domino DATETIME. For example, let's assume
you want to write a document item of type DATETIME where the value is equal
to myDate
(and myDate
is an instance of Date
). You might be tempted
to use toISOString()
like this:
Datetime: {
type: 'datetime',
data: myDate.toISOString()
},
Unfortunately, toISOString()
writes a value with millisecond precision.
Therefore, when you use Database.createDocument()
to write a document
containing the above item, the request will fail. You must format myDate
to
be no more precise than a hundredth of a second. In other words:
'2013-03-01T14:09:01.009Z' // Invalid (too precise)
'2013-03-01T14:09:01.01Z' // Valid
Usually, this means you will want to use an existing Node.js package to format and parse date values for use by domino-db. For example, moment is one good package for handling dates, but ultimately it is up to you to find the package that meets your needs.
HINT: If you are using moment, use the following format string for parsing and writing date values:
'YYYY-MM-DDTHH:mm:ss.SS[Z]'
.
Names, Readers and Authors items
A Names item is a text or text list item with a names
property set to true
:
From: {
type: 'text',
names: true,
data: 'CN=Joe Smith/O=Renovations',
}
A Names item value is usually a flat name (e.g. a group named 'Accounting'
),
a distinguished name (e.g. 'CN=Joe Smith/O=Renovations"
), or an email address
(e.g. 'jsmith@renovations.com'
). Abbreviated name values (e.g. 'Joe Smith/Renovations'
)
are discouraged.
A Readers item is a Names item with a readers
property set to true
:
Readers: {
type: 'text',
names: true,
readers: true,
data: ['CN=Joe Smith/O=Renovations', '[Admin]']
}
When a document includes a Readers item, you may open the document only if you
are in the list of readers. A Readers item value must be either a flat name, a
distinguished name, an email address, or an ACL role name (e.g. '[Admin]'
).
NOTE: Direct manipulation of a Readers item can be dangerous. If you write a Readers item that doesn't include your name, a group to which you belong, or a role you have, you may be unable to read the document you just saved. It may be safer to use compute-with-form instead of directly writing a Readers item.
An Authors item is a Names item with an authors
property set to true
:
Authors: {
type: 'text',
names: true,
authors: true,
data: ['CN=Joe Smith/O=Renovations', '[Approver]']
}
When a document includes an Authors item, you may update the document only if you are in the list of authors. An Authors item value must be one of the types allowed in a Readers item -- either a flat name, a distinguished name, an email address, or an ACL role name.
Readers and Authors lists are very powerful features embedded in core Domino. For more information about these features, consult the relevant Domino documentation.
System properties
When you read a document, domino-db includes the following system properties. These properties are read-only. When you create or update a document, system properties are ignored.
@attachments
Description: An array of attachment summaries. This property is included
only if the document has attachments and your read options
object includes
readAttachmentSummaries: true
.
Type: Array of objects
Example
'@attachments': [
{
fileSize: 1245861,
fileName: 'adams.jpg',
modified: {
type: 'datetime',
data: '2019-05-20T17:35:03.01Z'
}
},
{
fileSize: 1204218,
fileName: 'jefferson.jpg',
modified: {
type: 'datetime',
data: '2019-05-20T17:36:06.75Z'
}
}
]
@created
Description: When the document was originally created.
Type: datetime
Example
'@created': {
type: 'datetime',
data: '2018-07-30T15:37:34.07Z'
}
@modified
Description: When the document was last modified.
Type: datetime
Example
'@modified': {
type: 'datetime',
data: '2018-07-30T15:37:35.09Z'
}
@unid
Description: The document's universal ID. This ID is the same across all replicas of the database.
Type: string
Example
'@unid': '4A51270A49D9C592852582DA0055D63F',