docs.intersystems.com
Home  /  Application Development: Additional Options  /  Using Document Database (DocDB)  /  Managing Documents


Using Document Database (DocDB)
Managing Documents
[Back]  [Next] 
InterSystems: The power behind what matters   
Search:  


InterSystems IRIS Data Platform™ DocDB supplies class methods that enable you to work with DocDB from ObjectScript. For further details on invoking JSON methods from ObjectScript, refer to the Using JSON manual.
This chapter describes methods to perform the following operations:
Create or Get a Document Database
To create a new document database in the current namespace, invoke the %CreateDatabase() method.
To get an existing document database in the current namespace, invoke the %GetDatabase() method.
You assign a document database a unique name within the current namespace. The name can be qualified "packagename.docdbname" or unqualified. An unqualified database name defaults to the ISC.DM package.
The following example gets a database if a database with that name exists in the current namespace; otherwise, it creates the database:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
The following example creates or gets a database, then uses %GetDatabaseDefinition() to display the database definition information, which is stored as a JSON Dynamic Abstract Object:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
  SET defn = db.%GetDatabaseDefinition()
  WRITE defn.%ToJSON()
You can use %SYSTEM.DocDB.GetAllDatabases() to return a JSON array containing the names of all databases defined in this namespace.
Define a Property: %CreateProperty()
In order to retrieve a document by a key:value pair, you must use %CreateProperty() to define a property for that key. Defining a property automatically creates an index for that key which InterSystems IRIS maintains when documents are inserted, modified, and deleted. A property must specify a data type for the key. A property can be specified as accepting only unique values (1), or as non-unique (0); the default is non-unique.
The following example assigns two properties to the database. It then displays the database definition information:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
  DO db.%CreateProperty("firstName","%String","$.firstName",0) // creates non-unique property
  DO db.%CreateProperty("lastName","%String","$.lastName",1)   // create a unique property; an index to support uniqueness is automatically created
  WRITE db.%GetDatabaseDefinition().%ToJSON()
Insert or Replace a Document: %SaveDocument()
You can insert or replace a document in a database using either the documentID or data selection criteria.
The %SaveDocument() method saves a document. If you do not specify a documentId, it inserts a new document and generates a new documentId. If you specify a documentId, it replaces an existing document with that documentId. If you specify a documentId and that document does not exist, it generates an ERROR #5809 exception.
The document data consists of one or more key:value pairs. If you specify a duplicate value for a key property that is defined as unique, it generates an ERROR #5808 exception.
The following example inserts three new documents and assigns them documentIds. It then replaces the entire contents of the document identified by documentId 2 with the specified contents:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
    WRITE db.%Size(),!
  DO db.%CreateProperty("firstName","%String","$.firstName",0)
  SET val = db.%SaveDocument({"firstName":"Serena","lastName":"Williams"})
  SET val = db.%SaveDocument({"firstName":"Bill","lastName":"Faulkner"})
  SET val = db.%SaveDocument({"firstName":"Fred","lastName":"Astare"})
  WRITE "Contains ",db.%Size()," documents: ",db.%ToJSON()
  SET val = db.%SaveDocument({"firstName":"William","lastName":"Faulkner"},2)
  WRITE !,"Contains ",db.%Size()," documents: ",db.%ToJSON()
The following example chains the %Id() method to each %SaveDocument(), returning the documentId of each document as it is inserted or replaced:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
  DO db.%CreateProperty("firstName","%String","$.firstName",0)
  WRITE db.%SaveDocument({"firstName":"Serena","lastName":"Williams"}).%Id(),!
  WRITE db.%SaveDocument({"firstName":"Bill","lastName":"Faulkner"}).%Id(),!
  WRITE db.%SaveDocument({"firstName":"Fred","lastName":"Astare"}).%Id(),!
  WRITE "Contains ",db.%Size()," documents: ",db.%ToJSON()
  WRITE db.%SaveDocument({"firstName":"William","lastName":"Faulkner"},2).%Id(),!
  WRITE !,"Contains ",db.%Size()," documents: ",db.%ToJSON()
Count Documents in a Database: %Size()
To count the number of documents in a database, invoke the %Size() method:
  SET doccount = db.%Size()
  WRITE doccount
Get Document in a Database: %GetDocument()
To retrieve a single document from the database by %DocumentId, invoke the %GetDocument() method, as shown in the following example:
  DO db.%GetDocument(2).%ToJSON()
This method returns only the %Doc property contents. For example:
{"firstName":"Bill","lastName":"Faulkner"}
If the specified %DocumentId does not exist, %GetDocument() generates an ERROR #5809 exception: “Object to load not found”.
You can also return a single document from the database by %DocumentId, using the %FindDocuments() method. For example:
  DO db.%FindDocuments(["%DocumentId",2,"="]).%ToJSON()
This method returns the complete JSON document, including its wrapper:
{"sqlcode":100,"message":null,"content":[{"%Doc":"{\"firstName\":\"Bill\",\"lastName\":\"Faulkner\"}",
"%DocumentId":2,"%LastModified":"2018-03-06 18:59:02.559"}]}
Find Documents in a Database: %FindDocuments()
To find one or more documents in a database and return the document(s) as JSON, invoke the %FindDocuments() method. This method takes any combination of three optional positional predicates: a restriction array, a projection array, and a limit key:value pair.
The following examples, with no positional predicates, both return all of the data in all of the documents in the database:
  WRITE db.%FindDocuments().%ToJSON()
  WRITE db.%FindDocuments(,,).%ToJSON()
Restriction Predicate Array
The restriction predicate syntax ["property","value","operator"] returns the entire contents of the matching documents. You specify as search criteria the property, value, and operator as an array. If you do not specify the operator, it defaults to "=". You can specify more than one restriction as an array of restriction predicates with implicit AND logic: [["property","value","operator"],["property2","value2","operator2"]]. The restriction predicate is optional.
The following example returns all documents with a documentId greater than 2:
  SET result = db.%FindDocuments(["%DocumentId",2,">"])
  WRITE result.%ToJSON()
or by chaining methods:
  WRITE db.%FindDocuments(["%DocumentId",2,">"]).%ToJSON()
If the contents of documents match the search criteria, It returns results such as the following:
{"sqlcode":100,"message":null,"content":[{"%Doc":"{\"firstName\":\"Fred\",\"lastName\":\"Astare\"}","%DocumentId":"3","%LastModified":"2018-03-05 18:15:30.39"},{"%Doc":"{\"firstName\":\"Ginger\",\"lastName\":\"Rogers\"}","%DocumentId":"4","%LastModified":"2018-03-05 18:15:30.39"}]} 
If no documents match the search criteria, it returns:
{"sqlcode":100,"message":null,"content":[]}
To find a document by a key:value pair, you must have defined a document property for that key:
  IF $SYSTEM.DocDB.Exists("People")
    { SET db = ##class(%DocDB.Database).%GetDatabase("People")}
  ELSE {SET db = ##class(%DocDB.Database).%CreateDatabase("People") }
    WRITE db.%Size(),!
  DO db.%CreateProperty("firstName","%String","$.firstName",0)
  SET val = db.%SaveDocument({"firstName":"Serena","lastName":"Williams"})
  SET val = db.%SaveDocument({"firstName":"Bill","lastName":"Faulkner"})
  SET val = db.%SaveDocument({"firstName":"Fred","lastName":"Astare"})
  SET result = db.%FindDocuments(["firstName","Bill","="])
  WRITE result.%ToJSON()
Projection Predicate Array
To return only some of the values in returned documents you use a projection. The optional projection predicate is an array listing the keys for which you wish to return the corresponding values. If you specify a user-defined key in the projection array, you must have defined a document property for that key.
The projection predicate syntax ["property","value","operator"],["prop1","prop2",...] returns the specified properties from the matching documents.
  SET result = db.%FindDocuments(["firstName","Bill","="],["%DocumentId","firstName"])
  WRITE result.%ToJSON()
You can specify a projection with or without a restriction predicate. Thus both of the following are valid syntax:
Limit Predicate
You can specify a limit key:value predicate to return, at most, only the specified number of matching documents.
The syntax ["property","value","operator"],["prop1","prop2",...],{"limit":int} returns the specified properties from the specified limit number of documents.
  SET result = db.%FindDocuments(["firstName","Bill","="],["%DocumentID","firstName"],{"limit":5})
  WRITE result.%ToJSON()
This returns data from, at most, 5 documents.
You can specify a limit with or without a restriction predicate or a projection predicate. Thus all the following are valid syntax:
The following example specifies no restriction, a projection, and a limit:
  WRITE db.%FindDocuments(,["%DocumentId","lastName"],{"limit":3}).%ToJSON()
Query Documents in a Database: %ExecuteQuery()
You can use the %ExecuteQuery() method to return document data from a database as a result set. You specify a standard SQL query SELECT, specifying the database name in the FROM clause. If the database name was created with no package name (schema), specify the default ISC_DM schema.
The following example retrieves the %Doc content data as a result set from all documents in the database:
  SET rval=db.%ExecuteQuery("SELECT %Doc FROM ISC_DM.People")
  DO rval.%Display()
The following example uses a WHERE clause condition to limit what documents to retrieve by documentId value:
  SET rval=db.%ExecuteQuery("SELECT %DocumentId,%Doc FROM ISC_DM.People WHERE %DocumentId > 2")
  DO rval.%Display()
The following example retrieve the %DocumentId and the lastName property from all documents that fulfill the WHERE clause condition. Note that to retrieve the values of a user-defined key, you must have defined a document property for that key:
  SET rval=db.%ExecuteQuery("SELECT %DocumentId,lastName FROM ISC_DM.People WHERE lastName %STARTSWITH 'S'")
  DO rval.%Display()
For further information on handling a query result set, refer to Returning the Full Result Set or Returning Specific Values from the Result Set.
Delete a Document: %DeleteDocument()
You can delete documents from a database either by documentID or by data selection criteria.