Documents — Data Model
Overview
In Couchbase Lite, a document’s body takes the form of a JSON object — a collection of key/value pairs where the values can be different types of data such as numbers, strings, arrays or even nested objects. Every document is identified by a document ID, which can be automatically generated (as a UUID) or specified programmatically; the only constraints are that it must be unique within the database, and it can’t be changed.
Initializers
The following methods/initializers can be used:
-
The
MutableDocument()
initializer can be used to create a new document where the document ID is randomly generated by the database. -
The
MutableDocument(withID: String)
initializer can be used to create a new document with a specific ID. -
The
database.document(withID: String)
method can be used to get a document. If it doesn’t exist in the database, it will returnnil
. This method can be used to check if a document with a given ID already exists in the database.
The following code example creates a document and persists it to the database.
CBLMutableDocument *newTask = [[CBLMutableDocument alloc] init];
[newTask setString:@"task" forKey:@"task"];
[newTask setString:@"todo" forKey:@"owner"];
[newTask setString:@"task" forKey:@"createdAt"];
[database saveDocument:newTask error:&error];
Mutability
By default, when a document is read from the database it is immutable.
The document.toMutable()
method should be used to create an instance of the document which can be updated.
CBLDocument *document = [database documentWithID:@"xyz"];
CBLMutableDocument *mutableDocument = [document toMutable];
[mutableDocument setString:@"apples" forKey:@"name"];
[database saveDocument:mutableDocument error:&error];
Changes to the document are persisted to the database when the saveDocument
method is called.
Typed Accessors
The Document
class now offers a set of property accessors
for various scalar types, including boolean, integers, floating-point and strings.
These accessors take care of converting to/from JSON encoding, and make sure you get the type you’re expecting.
In addition, as a convenience we offer Date
accessors.
Dates are a common data type, but JSON doesn’t natively support them, so the convention is to store them as strings in ISO-8601 format.
The following example sets the date on the createdAt
property and reads it back using the document.date(forKey: String)
accessor method.
[newTask setValue:[NSDate date] forKey:@"createdAt"];
NSDate *date = [newTask dateForKey:@"createdAt"];
If the property doesn’t exist in the document it will return the default value for that getter method (0 for getInt
, 0.0 for getFloat
etc.).
If you need to determine whether a given property exists in the document, you should use the [Document contains:key]
method.
Batch operations
If you’re making multiple changes to a database at once, it’s faster to group them together. The following example persists a few documents in batch.
[database inBatch:&error usingBlock:^{
for (int i = 0; i < 10; i++) {
CBLMutableDocument *doc = [[CBLMutableDocument alloc] init];
[doc setValue:@"user" forKey:@"type"];
[doc setValue:[NSString stringWithFormat:@"user %d", i] forKey:@"name"];
[doc setBoolean:NO forKey:@"admin"];
[database saveDocument:doc error: &error];
}
}];
At the local level this operation is still transactional: no other Database
instances, including ones managed by the replicator can make changes during the execution of the block, and other instances will not see partial changes.
But Couchbase Mobile is a distributed system, and due to the way replication works, there’s no guarantee that Sync Gateway or other devices will receive your changes all at once.
Document Expiration
Document expiration allows users to set the expiration date to a document. When the document is expired, the document will be purged from the database. The purge will not be replicated to Sync Gateway.
The following example sets the TTL for a document to 5 minutes from the current time.
// Purge the document one day from now
NSDate* ttl = [[NSCalendar currentCalendar] dateByAddingUnit: NSCalendarUnitDay
value: 1
toDate: [NSDate date]
options: 0];
[database setDocumentExpirationWithID:@"doc123" expiration:ttl error:&error];
// Reset expiration
[database setDocumentExpirationWithID:@"doc1" expiration:nil error: &error];
// Query documents that will be expired in less than five minutes
NSTimeInterval fiveMinutesFromNow = [[NSDate dateWithTimeIntervalSinceNow:60 * 5] timeIntervalSince1970];
CBLQuery* query = [CBLQueryBuilder select: @[[CBLQuerySelectResult expression: [CBLQueryMeta id]]]
from: [CBLQueryDataSource database: database]
where: [[CBLQueryMeta expiration]
lessThan: [CBLQueryExpression double: fiveMinutesFromNow]]];