Skip to main content

Getting Started with Optic

Joining View and Triples Data

With the triples data we leveraged in the last example to retrieve Northeastern states and our employee view with its State column, we can find all our employees in the Northeast by building a multi-model query. We will use the now-familiar fromView() along with fromTriples(), which we introduced in the last section.

An Optic query like this one performs an inner join of a view and triples on a matching column, with the row sequence from the view acting as the “left table,” and the row sequence from the triples acting as the “right table”:

// SELECT FROM EMPLOYEE VIEW
const employees = op.fromView('Employee', 'Profile');

// SELECT WITH CATEGORY EXPANSION VIA TRIPLES
const ex    = op.prefixer('https://example.com/semantics/geo#');
const rdfs  = op.prefixer('http://www.w3.org/2000/01/rdf-schema#');
const skos  = op.prefixer('http://www.w3.org/2004/02/skos/core#');

const state = op.col('state')

const regionalStates = 
op.fromTriples([
   op.pattern(state, skos('broader'), ex('Northeast')),
   op.pattern(state, rdfs('isDefinedBy'), op.col('code'))
])

// JOIN VARYING DATA MODELS TO CREATE A MULTI-MODEL QUERY
employees
  .joinInner(regionalStates, op.on(employees.col('State'), regionalStates.col('code')))
  .offsetLimit(0, 100)
  .result();

We used this query to retrieve a row sequence with all columns from our Employee Profile view and all columns from the triples row sequence we generated previously in Building Semantic Queries where there is an employee document whose State column matches a triples code column:

  • The Data Accessor Function fromView() pulls data indexed for the view Profile associated with the schema Employee into a row sequence of this view’s columns.

  • The Data Accessor Function fromTriples() pulls data into a row sequence containing state and code as its columns based on the pattern provided as explained in the previous example.

  • When you use more than one data accessor function in a query, it is best practice to use a variable to represent each one to keep the query simple and readable.

  • The Operator Function joinInner() returns all rows from both the view and the triples if the specified columns match, considering the data accessor function specified first in the query to be the "left table" and the second to be the "right table."

  • The Auxiliary Function on() lets you specify a join condition for join-type operator functions like joinInner().

  • col() identifies the column in its argument.

  • The Operator Function offsetLimit() restricts results returned. The first parameter specifies the number of results to skip; the second, the number of results to return. So, (0, 100) returns the first 100 results.

  • The Executor Function result() executes the query and returns the results as a row sequence.

Here is row 1 of the 100-row x 25-column result:

{
  "Employee.Profile.GUID": "f172c249-3f22-4ebb-a29f-aa2b88213d24", // EC1 
  "state": "https://example.com/semantics/geo#NY",                 //  TC1
  "Employee.Profile.HiredDate": "2019-08-20",                      // EC2
  "code": "NY",                                                    //  TC2 = EC10
  "Employee.Profile.Gender": "female",                             // EC3 
  "Employee.Profile.Title": "Ms.",                                 // EC4, etc. 
  "Employee.Profile.GivenName": "Thelma", 
  "Employee.Profile.MiddleInitial": "D", 
  "Employee.Profile.Surname": "Crider", 
  "Employee.Profile.StreetAddress": "2525 Shinn Street", 
  "Employee.Profile.City": "New York", 
  "Employee.Profile.State": "NY",                                  // EC10 = TC2
  "Employee.Profile.ZipCode": "10017", 
  "Employee.Profile.Country": "US", 
  "Employee.Profile.EmailAddress": "ThelmaDCrider@superrito.com", 
  "Employee.Profile.TelephoneNumber": "212-731-8336", 
  "Employee.Profile.TelephoneCountryCode": "1", 
  "Employee.Profile.Birthday": "9/28/91", 
  "Employee.Profile.NationalID": "115-03-1703", 
  "Employee.Profile.Point": "40.709812,-73.908279", 
  "Employee.Profile.BaseSalary": 82777, 
  "Employee.Profile.Bonus": 8278, 
  "Employee.Profile.Department": "Marketing", 
  "Employee.Profile.Status": "Active - Regular Exempt (Full-time)", 
  "Employee.Profile.ManagerGUID": "d0862e5d-5be6-473b-a500-3e3a852b2bb8"
}
  • This query returned 100 rows for view documents with matching triples documents.

  • The rows are in an unspecified order, which could change between executions. You can specify row order with the orderBy() operator function.

  • The 25 columns are the 23 from our "left table," the Employee Profile view (EC#) plus the 2 from our "right table," the triples row sequence (TC#).