Loading TOC...
Temporal Developer's Guide (PDF)

Temporal Developer's Guide — Chapter 2

Quick Start

You can configure MarkLogic Server to manage and query temporal data.

This chapter walks you through the procedures for configuring the Documents database to store temporal documents and for inserting and querying temporal documents. The following are the main sections:

Create Metadata Fields for the Valid and System Axes

The valid and system axis each make use of metadata fields that define the start and end times. For example, the following query creates the metadata fields to be used to store the valid and system axes.

JavaScript Example:

var admin = require("/MarkLogic/admin.xqy");
var config = admin.getConfiguration();
var dbid = xdmp.database("Documents");
var validStart = admin.databaseMetadataField("validStart");
var validEnd = admin.databaseMetadataField("validEnd");
var systemStart = admin.databaseMetadataField("systemStart");
var systemEnd = admin.databaseMetadataField("systemEnd");
config = admin.databaseAddField(config, dbid, validStart);
config = admin.databaseAddField(config, dbid, validEnd);
config = admin.databaseAddField(config, dbid, systemStart);
config = admin.databaseAddField(config, dbid, systemEnd);
admin.saveConfiguration(config);

XQuery Example:

xquery version "1.0-ml";
import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";

let $config := admin:get-configuration()
let $dbid := xdmp:database("Documents")
let $fieldspec1 := admin:database-metadata-field("validStart")
let $fieldspec2 := admin:database-metadata-field("validEnd")
let $fieldspec3 := admin:database-metadata-field("systemStart")
let $fieldspec4 := admin:database-metadata-field("systemEnd")
for $fieldspec in ($fieldspec1, $fieldspec2, $fieldspec3, $fieldspec4)
let $new-config := admin:database-add-field($config, $dbid, $fieldspec)
return admin:save-configuration($new-config)

Create Range Field Indexes for the Valid and System Axes

The valid and system axis each make use of dateTime range field indexes that define the start and end times. For example, the following query creates the field range indexes to be used to create the valid and system axes.

JavaScript Example:

var admin = require("/MarkLogic/admin.xqy");
var config = admin.getConfiguration();
var dbid = xdmp.database("Documents");
var validStart = admin.databaseRangeFieldIndex(
    "dateTime", "validStart", "", fn.true() );
var validEnd   = admin.databaseRangeFieldIndex(
    "dateTime", "validEnd", "", fn.true() );
var systemStart = admin.databaseRangeFieldIndex(
    "dateTime", "systemStart", "", fn.true() );
var systemEnd   = admin.databaseRangeFieldIndex(
    "dateTime", "systemEnd", "", fn.true() );
config = admin.databaseAddRangeFieldIndex(config, dbid, validStart);
config = admin.databaseAddRangeFieldIndex(config, dbid, validEnd);
config = admin.databaseAddRangeFieldIndex(config, dbid, systemStart);
config = admin.databaseAddRangeFieldIndex(config, dbid, systemEnd);
admin.saveConfiguration(config);

XQuery Example:

xquery version "1.0-ml";
import module namespace admin = "http://marklogic.com/xdmp/admin" 
    at "/MarkLogic/admin.xqy";
let $config := admin:get-configuration()
let $dbid := xdmp:database("Documents")
let $rangespec1 := admin:database-range-field-index(
                    "dateTime", "validStart", "", fn:true() )
let $rangespec2 := admin:database-range-field-index(
                    "dateTime", "validEnd", "", fn:true() )
let $rangespec3 := admin:database-range-field-index(
                    "dateTime", "systemStart", "", fn:true() )
let $rangespec4 := admin:database-range-field-index(
                    "dateTime", "systemEnd", "", fn:true() )
for $rangespec in ($rangespec1, $rangespec2, $rangespec3, $rangespec4)
let $new-config := admin:database-add-range-field-index(
                    $config, $dbid, $rangespec)
return admin:save-configuration($new-config)

Create System and Valid Axes

On the Documents database, create two axes, named 'valid' and 'system,' each to serve as a container for a named pair of field range indexes.

JavaScript Example:

var temporal = require("/MarkLogic/temporal.xqy");
var validResult = temporal.axisCreate(
    "valid", 
    cts.fieldReference("validStart", "type=dateTime"), 
    cts.fieldReference("validEnd", "type=dateTime"));
var systemResult = temporal.axisCreate(
    "system", 
    cts.fieldReference("systemStart", "type=dateTime"), 
    cts.fieldReference("systemEnd", "type=dateTime"));

XQuery Example:

xquery version "1.0-ml"; 
import module namespace temporal = "http://marklogic.com/xdmp/temporal" 
    at "/MarkLogic/temporal.xqy";
temporal:axis-create(
    "valid",
    cts:field-reference("validStart", "type=dateTime"),
    cts:field-reference("validEnd", "type=dateTime"));
xquery version "1.0-ml"; 
import module namespace temporal = "http://marklogic.com/xdmp/temporal" 
    at "/MarkLogic/temporal.xqy";
temporal:axis-create(
    "system",
    cts:field-reference("systemStart", "type=dateTime"),
    cts:field-reference("systemEnd", "type=dateTime"))

Create a Temporal Collection

Create a temporal collection, named 'kool,' that uses the previously created 'system' and 'valid' axes.

JavaScript Example:

var temporal = require("/MarkLogic/temporal.xqy");
var collectionResult = temporal.collectionCreate(
"kool", "system", "valid");

XQuery Example:

xquery version "1.0-ml";
import module namespace temporal = "http://marklogic.com/xdmp/temporal" 
     at "/MarkLogic/temporal.xqy";
temporal:collection-create("kool", "system", "valid")

Axis and temporal collection names are case-sensitive.

Insert Some Temporal Documents

Insert some documents into the temporal collection. In this example, a stock trader, John, places an order to buy some stock. The record of the trade is stored as a bi-temporal document, as follows:

  1. The stock of KoolCo is trading around $12.65. John places a limit order to buy 100 shares of the stock for $12 at 11:00:00 on 3-Apr-2014 (this is the valid time). The document for the transaction is recorded in the broker's database at 11:00:01 on 3-Apr-2014 (this is the system time).

    JavaScript Example:

    declareUpdate();
    var temporal = require("/MarkLogic/temporal.xqy");
    var root =
        {"tempdoc": 
           {"trader": "John",
            "price": 12}
        };
    var options =
        {metadata:
           {validStart: "2014-04-03T11:00:00",
            validEnd: "2014-04-03T16:00:00"}
        };
    temporal.documentInsert("kool", "koolorder.json", root, options);

    XQuery Example:

    xquery version "1.0-ml";
    import module namespace temporal = "http://marklogic.com/xdmp/temporal" 
        at "/MarkLogic/temporal.xqy";   
    let $root :=   
    <tempdoc>
        <trader>John</trader> 
        <content>12</content>  
    </tempdoc>
    let $options :=  
    <options xmlns="xdmp:document-insert">
        <metadata>
           <map:map xmlns:map="http://marklogic.com/xdmp/map">
             <map:entry key="validStart">
               <map:value>2014-04-03T11:00:00</map:value>
             </map:entry>
             <map:entry key="validEnd">
               <map:value>2014-04-03T16:00:00</map:value>
             </map:entry> 
           </map:map>
        </metadata> 
    </options> 
    return 
    temporal:document-insert("kool", "koolorder.xml", $root, $options)

    You can use xdmp.documentGetMetadata to display the metadata for a temporal document. For example: xdmp.documentGetMetadata("koolorder.json")

  2. John looks at the trading pattern of the stock over the last week and notices that it always dips during the last minute of the trading day. At 11:30:00, John changes his order to buy the stock at the closing price (15:59:59). The change is recorded as another document in the broker's database at 11:30:01.

    JavaScript Example:

    declareUpdate();
    var temporal = require("/MarkLogic/temporal.xqy");
    var root =
        {"tempdoc": 
           {"trader": "John",
            "price": "Closing Price"}
        };
    var options =
        {metadata:
           {validStart: "2014-04-03T15:59:59",
            validEnd: "2014-04-03T16:00:00"}
        };
    temporal.documentInsert("kool", "koolorder.json", root, options);

    XQuery Example:

    xquery version "1.0-ml";
    import module namespace temporal = "http://marklogic.com/xdmp/temporal" 
        at "/MarkLogic/temporal.xqy";   
    let $root :=   
    <tempdoc>
        <trader>John</trader> 
        <content>Closing Price</content>  
    </tempdoc>
    let $options :=  
    <options xmlns="xdmp:document-insert">
        <metadata>
           <map:map xmlns:map="http://marklogic.com/xdmp/map">
             <map:entry key="validStart">
               <map:value>2014-04-03T15:59:59</map:value>
             </map:entry>
             <map:entry key="validEnd">
               <map:value>2014-04-03T16:00:00</map:value>
             </map:entry> 
           </map:map>
        </metadata> 
    </options> 
    return 
    temporal:document-insert("kool", "koolorder.xml", $root, $options)

    The result should be three documents with valid and system times as show in the graphic below. Note that the second query resulted in a split on Doc 1 that resulted in Doc 2, as well as Doc 3 that contains the new content.

Run some Search Queries on the Temporal Documents

The following query searches the temporal documents, using the cts:period-range-query function to locate the documents that were in the database between 11:10 and 11:15. ISO_CONTAINS is one of the comparison operators described in ISO SQL 2011 Operators.

In this example, only Doc 1 meets the search criteria.

JavaScript Example:

cts.search(cts.periodRangeQuery(
    "system",
    "ISO_CONTAINS",
    cts.period(xs.dateTime("2014-04-03T11:10:00"),
               xs.dateTime("2014-04-03T11:15:00")) ));

XQuery Example:

xquery version "1.0-ml";
cts:search(fn:doc(), cts:period-range-query(
    "system",
    "ISO_CONTAINS",
    cts:period(xs:dateTime("2014-04-03T11:10:00"),
               xs:dateTime("2014-04-03T11:15:00")) ))

The following query searches the temporal documents, using the cts:period-range-query function to locate the documents that have a valid time period that starts after 10:30 and ends at 15:59. ALN_FINISHES is one of the comparison operators described in Allen Operators.

In this example, only Doc 2 meets the search criteria.

JavaScript Example:

cts.search(cts.periodRangeQuery(
    "valid",
    "ALN_FINISHES",
    cts.period(xs.dateTime("2014-04-03T10:30:00"),
               xs.dateTime("2014-04-03T15:59:59")) ));

XQuery Example:

xquery version "1.0-ml";
cts:search(fn:doc(), cts:period-range-query(
   "valid",
   "ALN_FINISHES",
   cts:period(xs:dateTime("2014-04-03T10:30:00"),
              xs:dateTime("2014-04-03T15:59:59")) ))

The following query searches the temporal documents, using the cts:period-range-query function to locate the documents that were in the database after 11:20. ALN_AFTER is one of the comparison operators described in Allen Operators.

In this example, both Doc 2 and Doc 3 meet the search criteria.

JavaScript Example:

cts.search(cts.periodRangeQuery(
    "system",
    "ALN_AFTER",
    cts.period(xs.dateTime("2014-04-03T11:00:00"),
               xs.dateTime("2014-04-03T11:20:00")) ));

XQuery Example:

xquery version "1.0-ml";
cts:search(fn:doc(), cts:period-range-query(
   "system",
   "ALN_AFTER",
   cts:period(xs:dateTime("2014-04-03T11:00:00"),
              xs:dateTime("2014-04-03T11:20:00")) ))

The following query searches the temporal documents, using the cts:period-compare-query function to locate the documents that were in the database when the valid time period is within the system time period. ISO_CONTAINS is one of the comparison operators described in ISO SQL 2011 Operators.

In this example, only Doc 3 meets the search criteria.

JavaScript Example:

cts.search(cts.periodCompareQuery(
    "system",
    "ISO_CONTAINS",
     "valid" ))

XQuery Example:

xquery version "1.0-ml";
cts:search(fn:doc(), cts:period-compare-query(
   "system",
   "ISO_CONTAINS",
   "valid" ))

The following query uses the cts:and-query to AND two cts:collection-query functions to return the temporal document that is in the URI collection, koolorder.xml, and the latest collection.

In this example, Doc 3 meets the search criteria.

JavaScript Example:

cts.search(cts.andQuery([
    cts.collectionQuery("koolorder.json"),
    cts.collectionQuery("latest")]))

XQuery Example:

xquery version "1.0-ml";
cts:search(fn:doc(), cts:and-query((
    cts:collection-query(("koolorder.xml")),
    cts:collection-query(("latest")))))

« Previous chapter
Next chapter »
Powered by MarkLogic Server 7.0-4.1 and rundmc | Terms of Use | Privacy Policy